Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[refactor] : DDD구조 변경 및 코드 리뷰를 기반으로 1차 리팩토링을 진행한다 #90

Closed
wants to merge 68 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
f90f3d1
#78 [feat] : Presentation Layer에서 처리하기 위한 토큰 정보 DTO를 추가한다
bbbang105 Nov 21, 2024
5f1f97d
#78 [feat] : Jwt 토큰 관련 설정값을 관리한다
bbbang105 Nov 21, 2024
ba9091e
#78 [feat] : Global Error를 세분화한다
bbbang105 Nov 21, 2024
09c9a03
#78 [feat] : 주석을 추가하고 유효기간을 반환하는 기능을 추가한다
bbbang105 Nov 21, 2024
4947f22
#78 [refactor] : 핸들러에서는 요청 처리와 리다이렉트만을 담당하도록 변경한다
bbbang105 Nov 21, 2024
a4b16f3
#78 [refactor] : HTTP 프로토콜은 Presentation Layer에서 처리하도록 변경한다
bbbang105 Nov 21, 2024
fbb2e2a
#78 [refactor] : 매직넘버를 제거하고 기능을 추가한다
bbbang105 Nov 21, 2024
ded0bf2
#78 [feat] : Redis 관련 에러 코드를 추가한다
bbbang105 Nov 21, 2024
2aa9548
#78 [feat] : 테스트 코드를 수정한다
bbbang105 Nov 21, 2024
6e6450a
#78 [style] : DTO 이름을 변경한다
bbbang105 Nov 23, 2024
ccc6860
#78 [style] : 제거된 주석을 복구한다
bbbang105 Nov 23, 2024
c0f3a54
#78 [refactor] : 리다이렉트 URL 설정 값도 Util을 통해 가져오는 방식으로 변경한다
bbbang105 Nov 23, 2024
512a563
#78 [feat] : 레디스 관련 환경변수 값을 추가한다
bbbang105 Nov 23, 2024
13cce95
#78 [refactor] : 에러 처리를 위해 null 값을 허용한다
bbbang105 Nov 23, 2024
c8794ab
Merge pull request #79 from KUSITMS-30th-TEAM-A/feature/#78/first-ref…
bbbang105 Nov 23, 2024
07d14f0
#78 [refactor] : Enum 컨벤션을 맞추기 위해 대문자로 변경한다
bbbang105 Nov 23, 2024
8b2be66
#78 [refactor] : stream을 사용하는 방식으로 리팩토링한다
bbbang105 Nov 23, 2024
f3bf9fe
#78 [refactor] : 메서드명과 반환 타입을 구체화한다
bbbang105 Nov 23, 2024
e29ac37
#78 [refactor] : 확장성을 고려하여 인터페이스를 구현하는 방식으로 리팩토링한다
bbbang105 Nov 23, 2024
caf8071
#78 [feat] : 챗봇 관련 에러 코드를 추가한다
bbbang105 Nov 23, 2024
b182571
#80 [refactor] Result 엔티티의 user와 stadium을 간접참조로 변경하고, result내에서 profi…
juuuunny Nov 23, 2024
335b232
#78 [refactor] profile과 zone의 result연결 메서드를 삽입한다.
juuuunny Nov 23, 2024
62223f0
#78 [feat] 스타디움명을 통하여 해당 스타디움의 id를 반환해주는 메소드를 추가한다.
juuuunny Nov 23, 2024
f3e29d3
#78 [feat] 유저id를 통하여 해당 유저 존재여부 확인 메서드를 추가한다.
juuuunny Nov 23, 2024
e3b76e8
#78 [refactor] resultService에서 타 어그리게이트의 레포지토리가 아닌 서비스를 호출하도록 로직을 변경한다.
juuuunny Nov 23, 2024
350c076
#78 [refactor] Result 서비스 내에서 객체탐색을 통하여 하위 엔티티를 찾을 수 있도록 변경한다.
juuuunny Nov 23, 2024
ff6fa39
#78 [refactor] result 어그리게이트의 dto를 응용계층으로 이동한다.:
juuuunny Nov 23, 2024
9c8d0eb
#78 [rename] resultService의 파일명을 resultApplicationService로 변경한다.
juuuunny Nov 23, 2024
689ddaa
#78 [refactor] result 어그리게이트의 presentation의 javadoc 주석을 변경하여 리팩토링을 진행한다.
juuuunny Nov 23, 2024
59fdbe5
#78 [rename] 추천받은 결과 저장 메소드명을 변경한다.
juuuunny Nov 23, 2024
c867ca7
#78 [refactor] : 클로바 API 호출 시 비동기로 처리하여 reactive 흐름을 유지한다
bbbang105 Nov 23, 2024
926f685
#78 [refactor] : 비동기 처리도 테스트할 수 있도록 변경한다
bbbang105 Nov 23, 2024
e4b0ee2
#78 [refactor] : DTO 이름을 변경한다
bbbang105 Nov 23, 2024
0075e43
#78 [style] : 챗봇 관련 주석을 추가한다
bbbang105 Nov 23, 2024
206f230
#78 [refactor] Result 어그리게이트의 application과 domai 리팩토링을 진행한다.
juuuunny Nov 23, 2024
27b7b9b
#78 [refactor] : global -> 타 도메인으로 의존성이 생기지 않도록 변경한다
bbbang105 Nov 23, 2024
e429e37
#78 [feat] : Redis를 활용하여 분산 락을 구현한다
bbbang105 Nov 23, 2024
d8583db
Merge pull request #87 from KUSITMS-30th-TEAM-A/feature/#78/refactor-…
bbbang105 Nov 23, 2024
8edac89
Merge pull request #85 from KUSITMS-30th-TEAM-A/feature/#78/refactor-…
bbbang105 Nov 23, 2024
0af0a06
#78 [refactor] Result 어그리거트의 전체적이 구조 리팩토링을 진행한다. (presentation, appli…
juuuunny Nov 24, 2024
2f16fc1
#78 [refactor] Stadium 도메인의 리팩토링을 DDD에 맞게 리팩토링한다.
juuuunny Nov 24, 2024
59594d1
#78 [refactor] culture를 stadium 어그리거트에 통합하고 DDD구조로 변경한다.
juuuunny Nov 25, 2024
94ccfde
#78 [chore] stadium에 로그 메시지를 추가한다.
juuuunny Nov 25, 2024
15b1907
#78 [refactor] 스타디움, 결과 테스트 코드를 수정한다.
juuuunny Nov 25, 2024
2868419
#78 [rename] querydsl custom Repository의 클래스명을 변경한다.
juuuunny Nov 25, 2024
754e42d
#78 [rename] result 도메인의 키워드에 따른 결과 반환 클래스들의 클래스명을 변경한다.
juuuunny Nov 25, 2024
a50ab0e
#78 [refactor] 구역 추천 결과 저장 시 repository에서 id가 아닌 Result 자체를 반환하도록 변경한다.
juuuunny Nov 25, 2024
0af522a
#78 [refactor] RecommendedTopRankedZonesManager의 메서드 분리를 하여 가독성을 좋게한다.
juuuunny Nov 25, 2024
d973259
#78 [refactor] RecommendedUserProfileManager의 메서드 분리를 하여 가독성을 좋게한다.
juuuunny Nov 25, 2024
b027498
#78 [rename] ResultRepositoryImpl이 클래스명을 변경한다.
juuuunny Nov 25, 2024
30fee7a
#78 [refactor] DB에 접근하지 않는 필요없는 트랜잭션은 제거한다.
juuuunny Nov 25, 2024
48066d2
#78 [refactor] 도메인에서는 BaseTimeEntity를 상속받지 않도록 변경한다.
juuuunny Nov 25, 2024
4d925eb
#78 [rename] Stadium 레포지토리의 Impl 부분의 클래스명을 변경한다.
juuuunny Nov 25, 2024
8073a95
#78 [chore] stadium과 result 어그리거트의 공백 및 개행문자 처리를 한다.(파일 가장 끝에는 엔터 1개)
juuuunny Nov 25, 2024
cbb59d0
#78 [chore] result 도메인의 기본 url을 변경한다.
juuuunny Nov 25, 2024
6ccefaf
#78 [refactor] Stadium 어그리거트에서 Food와 Entertainment 파일을 분리한다.
juuuunny Nov 25, 2024
e84f34a
#78 [feat] stadium 어그리거트의 테스트 코드를 리팩토링 한 것에 맞게 수정한다.
juuuunny Nov 25, 2024
e7bd5b4
#78 [feat] 즐길거리와 먹거리 url 변경에 따른 jwt Filter와 Spring Security Url을 변경해준다.
juuuunny Nov 25, 2024
851bb8d
#78 [chore] 테스트에서 잠실종합운동장을 잠실종합운동장 (잠실)로 변경한다.
juuuunny Nov 25, 2024
6d30113
#78 [chore] userId에 따른 유저 존재 여부의 메서드명을 변경한다.
juuuunny Nov 25, 2024
ee20869
#78 [refactor] stadium 어그리거트의 status enum을 분리한다.
juuuunny Nov 25, 2024
6ad12de
#78 [feat] userApplicationService의 충돌난 부분을 변경한다.
juuuunny Nov 25, 2024
6e282c7
Merge pull request #84 from KUSITMS-30th-TEAM-A/feature/#78/result-re…
juuuunny Nov 25, 2024
090f3d5
#78 [feat] Swagger 관련 에러를 수정한다.
juuuunny Nov 25, 2024
49ac4a9
#78 [feat] QDomain 중복 생성 문제를 해결한다.
juuuunny Nov 25, 2024
3fbca10
#78 [feat] QueryDsl Configuration 설정을 추가한다.
juuuunny Nov 26, 2024
8ac25d0
#78 [feat] refactor-v1과 develop 브랜치의 충돌을 해결한다.2
juuuunny Nov 26, 2024
24b377f
#78 [feat] refactor-v1과 develop 브랜치의 충돌을 해결한다.3
juuuunny Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,33 @@ dependencies {

}

def querydslDir = "src/main/generated"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17) // Java 버전
}
}

tasks.named('compileJava', JavaCompile).configure {
options.annotationProcessorGeneratedSourcesDirectory = file("$build/generated/sources/annotationProcessor/java/main")
}

sourceSets {
main {
java {
srcDirs += "$build/generated/sources/annotationProcessor/java/main"
}
}
}

tasks.named('compileJava') {
doFirst {
// QClass 파일 자동 삭제
def querydslGeneratedDir = layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main").get().asFile
if (querydslGeneratedDir.exists()) {
querydslGeneratedDir.deleteDir()
}
}
}
ext {
snippetsDir = file('build/generated-snippets')
}
Expand Down
39 changes: 13 additions & 26 deletions src/main/java/kusitms/backend/auth/application/AuthService.java
Original file line number Diff line number Diff line change
@@ -1,51 +1,38 @@
package kusitms.backend.auth.application;

import jakarta.servlet.http.HttpServletResponse;
import kusitms.backend.auth.dto.response.TokenResponseDto;
import kusitms.backend.auth.jwt.JWTUtil;
import kusitms.backend.auth.status.AuthErrorStatus;
import kusitms.backend.global.exception.CustomException;
import kusitms.backend.global.redis.RedisManager;
import kusitms.backend.global.util.CookieUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class AuthService {

@Value("${spring.jwt.access-token.expiration-time}")
private long ACCESS_TOKEN_EXPIRATION_TIME;

@Value("${spring.jwt.refresh-token.expiration-time}")
private long REFRESH_TOKEN_EXPIRATION_TIME;

private final JWTUtil jwtUtil;
private final RedisManager redisManager;

@Transactional
public void reIssueToken(String refreshToken, HttpServletResponse response) {
/**
* Refresh Token 검증 및 새로운 토큰 발급.
*
* @param refreshToken 클라이언트로부터 받은 리프레시 토큰
* @return 새로 생성된 Access Token과 Refresh Token
*/
public TokenResponseDto reIssueToken(String refreshToken) {
if (refreshToken == null) {
throw new CustomException(AuthErrorStatus._EXPIRED_REFRESH_TOKEN);
}
Long userId = jwtUtil.getUserIdFromToken(refreshToken);
String storedRefreshToken = redisManager.getRefreshToken(userId.toString());
if (!storedRefreshToken.equals(refreshToken)){
throw new CustomException(AuthErrorStatus._TOKEN_USER_MISMATCH);
}

jwtUtil.validateRefreshToken(storedRefreshToken);
String newAccessToken = jwtUtil.generateToken(userId, ACCESS_TOKEN_EXPIRATION_TIME); // 1시간 유효기간
String newRefreshToken = jwtUtil.generateToken(userId, REFRESH_TOKEN_EXPIRATION_TIME); // 14일 유효기간
redisManager.saveRefreshToken(userId.toString(), newRefreshToken);
Long userId = redisManager.validateAndExtractUserId(refreshToken);
String newAccessToken = jwtUtil.generateAccessOrRefreshToken(userId, jwtUtil.getAccessTokenExpirationTime());
String newRefreshToken = jwtUtil.generateAccessOrRefreshToken(userId, jwtUtil.getRefreshTokenExpirationTime());

CookieUtil.setCookie(response, "accessToken", newAccessToken, (int) (ACCESS_TOKEN_EXPIRATION_TIME * 1.5) / 1000);
CookieUtil.setCookie(response, "refreshToken", newRefreshToken, (int) REFRESH_TOKEN_EXPIRATION_TIME / 1000);
CookieUtil.setNotHttpOnlyCookie(response, "expirationTime", String.valueOf((int) ACCESS_TOKEN_EXPIRATION_TIME / 1000), (int) (ACCESS_TOKEN_EXPIRATION_TIME * 1.5) / 1000);
redisManager.saveRefreshToken(userId.toString(), newRefreshToken);
return new TokenResponseDto(newAccessToken, newRefreshToken, jwtUtil.getAccessTokenExpirationTime(), jwtUtil.getRefreshTokenExpirationTime());
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package kusitms.backend.auth.dto.response;

public record TokenResponseDto(
String accessToken,
String refreshToken,
long accessTokenExpiration,
long refreshTokenExpiration
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,46 @@

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import kusitms.backend.auth.dto.response.GoogleUserInfo;
import kusitms.backend.auth.dto.response.KakaoUserInfo;
import kusitms.backend.auth.dto.response.NaverUserInfo;
import kusitms.backend.auth.dto.response.OAuth2UserInfo;
import kusitms.backend.auth.jwt.JWTUtil;
import kusitms.backend.global.redis.RedisManager;
import kusitms.backend.global.util.CookieUtil;
import kusitms.backend.user.domain.entity.User;
import kusitms.backend.user.domain.repository.UserRepository;
import kusitms.backend.user.application.UserApplicationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Map;

@Slf4j
@Component
@RequiredArgsConstructor
public class OAuth2LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

@Value("${spring.jwt.redirect.onboarding}")
private String REDIRECT_URI_ONBOARDING; // 신규 유저 리다이렉트할 URI
@Value("${spring.jwt.redirect.base}")
private String REDIRECT_URI_BASE; // 기존 유저 리다이렉트할 URI

@Value("${spring.jwt.register-token.expiration-time}")
private long REGISTER_TOKEN_EXPIRATION_TIME;

@Value("${spring.jwt.access-token.expiration-time}")
private long ACCESS_TOKEN_EXPIRATION_TIME;

@Value("${spring.jwt.refresh-token.expiration-time}")
private long REFRESH_TOKEN_EXPIRATION_TIME;

private OAuth2UserInfo oAuth2UserInfo = null;
private final JWTUtil jwtUtil;
private final RedisManager redisManager;
private final UserRepository userRepository;

private final UserApplicationService userApplicationService;

/**
* OAuth2 로그인 성공 후 처리.
*
* @param request HTTP 요청 객체
* @param response HTTP 응답 객체
* @param authentication 인증 객체
* @throws IOException 리다이렉트 오류 발생 시 예외
*/
@Override
@Transactional
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
final String provider = token.getAuthorizedClientRegistrationId();
final Map<String, Object> attributes = token.getPrincipal().getAttributes();
switch (provider) {
case "kakao" -> oAuth2UserInfo = new KakaoUserInfo(attributes);
case "google" -> oAuth2UserInfo = new GoogleUserInfo(attributes);
case "naver" -> oAuth2UserInfo = new NaverUserInfo(attributes);
}

String providerId = oAuth2UserInfo.getProviderId();
String email = oAuth2UserInfo.getEmail();

User existUser = userRepository.findByProviderId(providerId);
if (existUser == null) {
log.info("신규 유저입니다.");
String registerToken = jwtUtil.generateRegisterToken(provider, providerId, email, REGISTER_TOKEN_EXPIRATION_TIME);
CookieUtil.setCookie(response, "registerToken", registerToken, (int) REGISTER_TOKEN_EXPIRATION_TIME / 1000);
getRedirectStrategy().sendRedirect(request, response, REDIRECT_URI_ONBOARDING);
} else {
log.info("기존 유저입니다.");
String accessToken = jwtUtil.generateToken(existUser.getId(), ACCESS_TOKEN_EXPIRATION_TIME);
String refreshToken = jwtUtil.generateToken(existUser.getId(), REFRESH_TOKEN_EXPIRATION_TIME);

redisManager.saveRefreshToken(existUser.getId().toString(), refreshToken);
CookieUtil.setCookie(response, "accessToken", accessToken, (int) (ACCESS_TOKEN_EXPIRATION_TIME * 1.5) / 1000);
CookieUtil.setCookie(response, "refreshToken", refreshToken, (int) REFRESH_TOKEN_EXPIRATION_TIME / 1000);
CookieUtil.setNotHttpOnlyCookie(response, "expirationTime", String.valueOf((int) ACCESS_TOKEN_EXPIRATION_TIME / 1000), (int) (ACCESS_TOKEN_EXPIRATION_TIME * 1.5) / 1000);
getRedirectStrategy().sendRedirect(request, response, REDIRECT_URI_BASE);
// 신규 사용자 처리
if (userApplicationService.isNewUser(token)) {
userApplicationService.handleNewUser(token, response);
getRedirectStrategy().sendRedirect(request, response, jwtUtil.getRedirectOnboardingUrl());
}
// 기존 사용자 처리
else {
userApplicationService.handleExistingUser(token, response);
getRedirectStrategy().sendRedirect(request, response, jwtUtil.getRedirectBaseUrl());
}
}
}
2 changes: 1 addition & 1 deletion src/main/java/kusitms/backend/auth/jwt/JWTFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected boolean shouldNotFilter(HttpServletRequest request) {
|| path.equals("/api/v1/token/re-issue")
|| path.equals("/api/v1/test/docs") || path.startsWith(("/swagger-ui")) || path.startsWith("/v3/api-docs")
|| path.startsWith("/api/v1/results") || path.startsWith("/api/v1/stadium")
|| path.startsWith("/api/v1/culture")
|| path.equals("/api/v1/foods") || path.equals("/api/v1/entertainments")
|| path.startsWith("/api/v1/chatbot")
;
}
Expand Down
Loading
Loading