diff --git a/README.md b/README.md
index 8b17e622..e9d8313c 100644
--- a/README.md
+++ b/README.md
@@ -69,8 +69,8 @@
- [ ] 실제 서비스를 공개적으로 배포하고 운영하는 경험을 해보았다.
- [ ] 유저의 피드백에 따라 성능/사용성을 개선하고 신규 기능을 추가해보았다.
- [ ] 발견되는 버그와 개선사항들을 정리하고 쌓인 이슈들을 체계적으로 관리해보았다.
-- [ ] 코드를 지속적으로 리팩토링하고 디자인 패턴을 적용해보았다.
-- [ ] 위의 시도에서 더 좋은 설계와 더 빠른 개발 사이의 트레이드 오프를 고민해본 적이 있다.
+- [X] 코드를 지속적으로 리팩토링하고 디자인 패턴을 적용해보았다.
+- [X] 위의 시도에서 더 좋은 설계와 더 빠른 개발 사이의 트레이드 오프를 고민해본 적이 있다.
- [ ] 반복되는 수정과 배포에 수반되는 작업들을 자동화 해보았다.
- [ ] 언어나 프레임워크만으로 구현할 수 없는 것들을 직접 구현해보았다.
- [ ] 내가 사용한 라이브러리나 프레임 워크의 한계를 느끼고 개선해보았다.
@@ -86,7 +86,7 @@
- WAS Server 내부에 Nginx를 통해 Reverse Proxy를 구현했습니다.
## ERD
-
+
- 현재 많은 부분이 수정되었고, 앞으로도 계속 수정될 예정입니다.
diff --git a/src/main/java/com/kcy/fitapet/domain/member/api/AuthApi.java b/src/main/java/com/kcy/fitapet/domain/member/api/AuthApi.java
index f10d50df..2af52292 100644
--- a/src/main/java/com/kcy/fitapet/domain/member/api/AuthApi.java
+++ b/src/main/java/com/kcy/fitapet/domain/member/api/AuthApi.java
@@ -66,8 +66,8 @@ public class AuthApi {
@PostMapping("/register")
@PreAuthorize("isAnonymous()")
public ResponseEntity> signUp(@RequestHeader("Authorization") @NotBlank String accessToken, @RequestBody @Valid SignUpReq dto) {
- Jwt tokens = memberAuthService.register(accessToken, dto);
- return getResponseEntity(tokens);
+ Pair result = memberAuthService.register(accessToken, dto);
+ return getResponseEntity(result.getKey(), result.getValue());
}
@Operation(summary = "회원가입 전화번호 인증")
@@ -138,11 +138,8 @@ public ResponseEntity> searchSmsAuthorization(
@PreAuthorize("isAnonymous()")
public ResponseEntity> signIn(@RequestBody @Valid SignInReq dto) {
Pair result = memberAuthService.login(dto);
- ResponseCookie cookie = cookieUtil.createCookie(REFRESH_TOKEN.getValue(), result.getValue().refreshToken(), 60 * 60 * 24 * 7);
- return ResponseEntity.ok()
- .header(HttpHeaders.SET_COOKIE, cookie.toString())
- .header(ACCESS_TOKEN.getValue(), result.getValue().accessToken())
- .body(SuccessResponse.from(Map.of("userId", result.getKey())));
+
+ return getResponseEntity(result.getKey(), result.getValue());
}
@Operation(summary = "로그아웃", description = "액세스 토큰과 리프레시 토큰을 만료시킵니다.")
@@ -188,7 +185,13 @@ public ResponseEntity> signOut(
@PreAuthorize("isAnonymous()")
public ResponseEntity> refresh(@CookieValue("refreshToken") @Valid String refreshToken) {
Jwt tokens = memberAuthService.refresh(refreshToken);
- return getResponseEntity(tokens);
+
+ ResponseCookie cookie = cookieUtil.createCookie(REFRESH_TOKEN.getValue(), tokens.refreshToken(), 60 * 60 * 24 * 7);
+
+ return ResponseEntity.ok()
+ .header(HttpHeaders.SET_COOKIE, cookie.toString())
+ .header(ACCESS_TOKEN.getValue(), tokens.accessToken())
+ .body(SuccessResponse.noContent());
}
@Operation(summary = "토큰 검증", description = "액세스 토큰의 유효성을 검사합니다.")
@@ -204,12 +207,12 @@ public ResponseEntity> verify(@AccessTokenInfo AccessToken accessToken) {
* @param tokens : 액세스 토큰과 리프레시 토큰
* @return ResponseEntity>
*/
- private ResponseEntity> getResponseEntity(Jwt tokens) {
+ private ResponseEntity> getResponseEntity(Long userId, Jwt tokens) {
ResponseCookie cookie = cookieUtil.createCookie(REFRESH_TOKEN.getValue(), tokens.refreshToken(), 60 * 60 * 24 * 7);
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.header(ACCESS_TOKEN.getValue(), tokens.accessToken())
- .body(SuccessResponse.noContent());
+ .body(SuccessResponse.from(Map.of("userId", userId)));
}
}
diff --git a/src/main/java/com/kcy/fitapet/domain/member/service/component/MemberAuthService.java b/src/main/java/com/kcy/fitapet/domain/member/service/component/MemberAuthService.java
index 439da6b3..ce4542cf 100644
--- a/src/main/java/com/kcy/fitapet/domain/member/service/component/MemberAuthService.java
+++ b/src/main/java/com/kcy/fitapet/domain/member/service/component/MemberAuthService.java
@@ -56,7 +56,7 @@ public class MemberAuthService {
private final PasswordEncoder bCryptPasswordEncoder;
@Transactional
- public Jwt register(String requestSmsAccessToken, SignUpReq dto) {
+ public Pair register(String requestSmsAccessToken, SignUpReq dto) {
String accessToken = jwtMapper.getProvider(SMS_AUTH_TOKEN).resolveToken(requestSmsAccessToken);
if (forbiddenTokenService.isForbidden(accessToken))
@@ -76,7 +76,7 @@ public Jwt register(String requestSmsAccessToken, SignUpReq dto) {
jwtMapper.getProvider(SMS_AUTH_TOKEN).getExpiryDate(accessToken), false)
);
- return generateToken(JwtUserInfo.from(registeredMember));
+ return Pair.of(registeredMember.getId(), generateToken(JwtUserInfo.from(registeredMember)));
}
@Transactional
diff --git a/src/main/java/com/kcy/fitapet/domain/oauth/api/OauthApi.java b/src/main/java/com/kcy/fitapet/domain/oauth/api/OauthApi.java
index feaed8c7..141974c7 100644
--- a/src/main/java/com/kcy/fitapet/domain/oauth/api/OauthApi.java
+++ b/src/main/java/com/kcy/fitapet/domain/oauth/api/OauthApi.java
@@ -18,6 +18,7 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hc.core5.http.HttpStatus;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
@@ -50,7 +51,7 @@ public ResponseEntity> signIn(
@RequestParam("provider") ProviderType provider,
@RequestBody @Valid OauthSignInReq req
) {
- Optional jwt;
+ Optional> jwt;
if (ProviderType.NAVER.equals(provider)) {
return null; // TODO: 2023-12-24 네이버 로그인 구현
} else {
@@ -58,7 +59,7 @@ public ResponseEntity> signIn(
}
return jwt.isPresent()
- ? getJwtResponseEntity(jwt.get())
+ ? getJwtResponseEntity(jwt.get().getKey(), jwt.get().getValue())
: ResponseEntity.ok(SuccessResponse.from(Map.of("id", req.id())));
}
@@ -76,14 +77,14 @@ public ResponseEntity> signUp(
@RequestHeader("Authorization") String accessToken,
@RequestBody @Valid OauthSignUpReq req
) {
- Jwt jwt;
+ Pair jwt;
if (ProviderType.NAVER.equals(provider)) {
return null; // TODO: 2023-12-24 네이버 로그인 구현
} else {
jwt = oAuthService.signUpByOIDC(id, provider, accessToken, req);
}
- return getJwtResponseEntity(jwt);
+ return getJwtResponseEntity(jwt.getKey(), jwt.getValue());
}
@Operation(summary = "OAuth 회원가입 전화번호 인증")
@@ -105,23 +106,23 @@ public ResponseEntity> signUpSmsAuthorization(
return ResponseEntity.ok(SuccessResponse.from(smsRes));
}
- Jwt token = oAuthService.checkCertificationNumber(req, id, code, provider);
- if (token == null)
+ Pair token = oAuthService.checkCertificationNumber(req, id, code, provider);
+ if (token.getValue() == null)
return ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).build();
- else if (token.refreshToken() == null)
+ else if (token.getValue().refreshToken() == null)
return ResponseEntity.ok()
- .header(ACCESS_TOKEN.getValue(), token.accessToken())
+ .header(ACCESS_TOKEN.getValue(), token.getValue().accessToken())
.body(SuccessResponse.from(Map.of("member", "신규 회원")));
- return getJwtResponseEntity(token);
+ return getJwtResponseEntity(token.getKey(), token.getValue());
}
- private ResponseEntity> getJwtResponseEntity(Jwt jwt) {
+ private ResponseEntity> getJwtResponseEntity(Long userId, Jwt jwt) {
ResponseCookie cookie = cookieUtil.createCookie(REFRESH_TOKEN.getValue(), jwt.refreshToken(), 60 * 60 * 24 * 7);
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.header(ACCESS_TOKEN.getValue(), jwt.accessToken())
- .body(SuccessResponse.noContent());
+ .body(SuccessResponse.from(Map.of("userId", userId)));
}
}
diff --git a/src/main/java/com/kcy/fitapet/domain/oauth/service/component/OauthService.java b/src/main/java/com/kcy/fitapet/domain/oauth/service/component/OauthService.java
index 5ede05f8..76d7a59a 100644
--- a/src/main/java/com/kcy/fitapet/domain/oauth/service/component/OauthService.java
+++ b/src/main/java/com/kcy/fitapet/domain/oauth/service/component/OauthService.java
@@ -30,6 +30,7 @@
import com.kcy.fitapet.global.common.util.sms.dto.SmsRes;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -59,14 +60,14 @@ public class OauthService {
private final SmsRedisHelper smsRedisHelper;
@Transactional
- public Optional signInByOIDC(String id, String idToken, ProviderType provider, String nonce) {
+ public Optional> signInByOIDC(String id, String idToken, ProviderType provider, String nonce) {
OIDCDecodePayload payload = getPayload(provider, idToken, nonce);
log.info("payload : {}", payload);
isValidRequestId(id, payload.sub());
if (oauthSearchService.isExistMember(new BigInteger(id), provider)) {
Member member = oauthSearchService.findMemberByOauthIdAndProvider(new BigInteger(id), provider);
- return Optional.of(generateToken(JwtUserInfo.from(member)));
+ return Optional.of(Pair.of(member.getId(), generateToken(JwtUserInfo.from(member))));
} else {
oidcTokenService.saveOIDCToken(idToken, provider, id);
return Optional.empty();
@@ -74,7 +75,7 @@ public Optional signInByOIDC(String id, String idToken, ProviderType provid
}
@Transactional
- public Jwt signUpByOIDC(String id, ProviderType provider, String requestOauthAccessToken, OauthSignUpReq req) {
+ public Pair signUpByOIDC(String id, ProviderType provider, String requestOauthAccessToken, OauthSignUpReq req) {
String accessToken = jwtMapper.getProvider(AuthConstants.SMS_OAUTH_TOKEN).resolveToken(requestOauthAccessToken);
JwtSubInfo subs = jwtMapper.getProvider(AuthConstants.SMS_OAUTH_TOKEN).getSubInfoFromToken(accessToken);
String phone = getPhoneByTopic(subs.phoneNumber());
@@ -98,7 +99,7 @@ public Jwt signUpByOIDC(String id, ProviderType provider, String requestOauthAcc
log.info("success oauth signup member id : {} - oauth id : {} [provider: {}]",
member.getId(), oauthAccount.getOauthId(), oauthAccount.getProvider());
- return generateToken(JwtUserInfo.from(member));
+ return Pair.of(member.getId(), generateToken(JwtUserInfo.from(member)));
}
@Transactional
@@ -113,7 +114,7 @@ public SmsRes sendCode(OauthSmsReq dto, ProviderType provider) {
}
@Transactional
- public Jwt checkCertificationNumber(OauthSmsReq req, String id, String code, ProviderType provider) {
+ public Pair checkCertificationNumber(OauthSmsReq req, String id, String code, ProviderType provider) {
String key = makeTopic(req.to(), provider);
log.info("key: {}", key);
if (!smsRedisHelper.isCorrectCode(key, code, SmsPrefix.OAUTH)) {
@@ -130,10 +131,10 @@ public Jwt checkCertificationNumber(OauthSmsReq req, String id, String code, Pro
oauthAccount.updateMember(member);
oidcTokenService.deleteOIDCToken(req.idToken());
- return generateToken(JwtUserInfo.from(member));
+ return Pair.of(member.getId(), generateToken(JwtUserInfo.from(member)));
}
- return Jwt.of(jwtMapper.getProvider(SMS_OAUTH_TOKEN).generateToken(SmsOauthInfo.of(id, key)), null);
+ return Pair.of(0L, Jwt.of(jwtMapper.getProvider(SMS_OAUTH_TOKEN).generateToken(SmsOauthInfo.of(id, key)), null));
}
/**