Conversation
- JWT 커스텀 필터 추가 - JWT 유틸리티 작성
- 테스트 컨트롤러 추가 - Entity 개발
- API 인가 refresh 분기처리 추가 - accesstoken 재발급 엔드포인트 개발 - Refresh Token JSON -> Cookie 변경 (secure, httponly 설정) - .http 테스트 코드 작성
- Auth 도메인 전역 예외 처리 및 커스텀 예외 적용 - Security Sevlet 예외 처리 적용 - .http 테스트 코드 추가
- security context에서 userId 가져올 수 있도록 커스텀 클래스 추가 - 테스트 로그 추가
|
Caution Review failedThe pull request is closed. Walkthrough인증 흐름과 예외 처리를 도메인 특화 예외로 정리하고 ApiResponse에 HTTP 상태 필드를 추가했습니다. Spring Security용 CustomUserDetails·필터·토큰 공급자 로직이 변경되며 컨트롤러 응답이 모두 ApiResponse(status, ...) 형태로 일관화되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant JwtFilter as JwtAuthenticationFilter
participant JwtProvider as JwtTokenProvider
participant AuthService
participant DB as UserRepository/DB
Client->>JwtFilter: 요청(Authorization or cookie)
alt 공개 엔드포인트
JwtFilter-->>Client: pass through (no auth)
else 토큰 있음
JwtFilter->>JwtProvider: validateToken(token)
alt 토큰 만료
JwtProvider-->>JwtFilter: throw ExpiredTokenException
JwtFilter-->>Client: JSON error (Expired token)
else 토큰 무효
JwtProvider-->>JwtFilter: throw InvalidTokenException
JwtFilter-->>Client: JSON error (Invalid token)
else 유효
JwtProvider->>AuthService: get userId / token claims
AuthService->>DB: load user
DB-->>AuthService: user
AuthService-->>JwtFilter: authentication principal
JwtFilter->>Client: continue filter chain (authenticated)
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45분 주의 검사 포인트:
Possibly related PRs
개요인증 시스템을 도메인 특화 예외로 리팩토링하고, ApiResponse에 HTTP 상태 코드를 추가하며, Spring Security의 CustomUserDetails를 구현하고, 모든 인증 엔드포인트를 상태 코드가 명시된 래핑된 응답을 반환하도록 업데이트했습니다. 변경 사항
예상 코드 리뷰 노력🎯 4 (복잡함) | ⏱️ ~45분 주의가 필요한 영역:
관련된 PR
시
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
🧹 Nitpick comments (12)
src/main/java/team/wego/wegobackend/common/security/SecurityConfig.java (1)
31-35:PathRequest.toH2Console()사용을 권장합니다.하드코딩된
"/h2-console/**"대신PathRequest.toH2Console()을 사용하면spring.h2.console.path속성과 자동으로 연동되어 유지보수성이 향상됩니다.+import org.springframework.boot.autoconfigure.security.servlet.PathRequest; ... .authorizeHttpRequests((auth) -> auth - .requestMatchers("/h2-console/**").permitAll() + .requestMatchers(PathRequest.toH2Console()).permitAll()또한, 프로덕션 환경에서는 H2 콘솔 접근을 비활성화하는 것이 보안상 권장됩니다 (예:
@Profile("dev")조건부 설정).src/main/java/team/wego/wegobackend/common/exception/GlobalExceptionHandler.java (1)
263-265: 사용되지 않는 파라미터를 제거하세요.
toProblemType메서드가 이제 상수만 반환하므로title파라미터가 사용되지 않습니다. 메서드를 파라미터 없이 단순화하거나 상수를 직접 사용하도록 리팩터링하는 것이 좋습니다.다음 diff를 적용하여 리팩터링하세요:
- private static String toProblemType(String title) { + private static String toProblemType() { return PROBLEM_BASE_URI; }그리고 모든 호출 부분에서 파라미터를 제거하세요:
- String type = toProblemType(title); + String type = toProblemType();src/main/java/team/wego/wegobackend/auth/application/AuthService.java (2)
17-17: 사용되지 않는 import 제거 권장
AppErrorCode는 이 파일에서 직접 사용되지 않습니다. 예외 클래스들이 내부적으로 사용하므로 이 import는 제거할 수 있습니다.-import team.wego.wegobackend.common.exception.AppErrorCode;
66-72: 삭제된 사용자 확인 순서 변경 권장현재 로직에서는 비밀번호 검증 후 삭제된 사용자를 확인합니다. 이 순서는 타이밍 공격(timing attack)에 취약할 수 있으며, 삭제된 계정에 대해서도 비밀번호 검증이 수행됩니다. 삭제된 사용자 확인을 비밀번호 검증 전에 수행하는 것이 보안상 더 좋습니다.
User user = userRepository.findByEmail(request.getEmail()) .orElseThrow(UserNotFoundException::new); + if (user.getDeleted()) { + throw new DeletedUserException(); + } + if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) { throw new InvalidPasswordException(); } - - if (user.getDeleted()) { - throw new DeletedUserException(); - }src/main/java/team/wego/wegobackend/user/presentation/UserController.java (2)
24-24: 로깅 형식 개선 권장
LocalDateTime.now()문자열 연결은 비효율적이며, 대부분의 로깅 프레임워크가 타임스탬프를 자동으로 추가합니다. SLF4J 플레이스홀더 패턴을 사용하세요.-log.info(LocalDateTime.now() + "test endpoint call, userId -> {}", userDetails.getId()); +log.info("test endpoint call, userId -> {}", userDetails.getId());
21-32: 테스트 엔드포인트 프로덕션 배포 전 제거 고려
/api/v1/user/test엔드포인트가 개발/테스트 목적으로 보입니다. 프로덕션 배포 전에 제거하거나, 특정 프로파일에서만 활성화되도록@Profile("dev")어노테이션 사용을 고려하세요.src/main/java/team/wego/wegobackend/common/exception/AppErrorCode.java (1)
25-31: 인증/인가 관련 에러 코드 추가 - LGTM!도메인별 에러 코드가 적절한 HTTP 상태 코드와 함께 추가되었습니다.
선택적 개선 사항:
ALREADY_EXISTS_USER의 경우HttpStatus.CONFLICT(409)가 리소스 충돌을 더 명확하게 표현할 수 있습니다. 현재 BAD_REQUEST도 동작에는 문제없습니다.src/main/java/team/wego/wegobackend/common/security/jwt/JwtTokenProvider.java (1)
3-21: 사용되지 않는 import 제거 필요다음 import들이 현재 파일에서 사용되지 않습니다:
HttpServletResponse(Line 9)IOException(Line 10)ErrorResponse(Line 19)import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.SignatureException; import jakarta.annotation.PostConstruct; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; import java.time.LocalDateTime; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; import java.util.Date; -import team.wego.wegobackend.common.response.ErrorResponse; import team.wego.wegobackend.common.security.exception.ExpiredTokenException; import team.wego.wegobackend.common.security.exception.InvalidTokenException;src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java (3)
9-9: 사용되지 않는 import.
HttpStatusCode가 import 되었지만 코드에서 사용되지 않습니다.-import org.springframework.http.HttpStatusCode;
96-98: 도메인 예외 대신 IllegalArgumentException 사용.PR 목표에 따르면 공통 예외 처리를 적용하는 것인데, 여기서는
IllegalArgumentException을 사용하고 있습니다. 다른 인증 관련 예외들처럼 도메인별 예외(예:InvalidTokenException)를 사용하는 것이 일관성 있습니다.if (refreshToken == null) { - throw new IllegalArgumentException("Refresh 토큰이 없습니다."); + throw new InvalidTokenException("Refresh 토큰이 없습니다."); }
102-108: 토큰 재발급에 201 CREATED 사용.토큰 재발급은 새로운 리소스 생성이 아니라 기존 토큰의 갱신입니다. 200 OK가 더 적절한 상태 코드입니다.
return ResponseEntity - .status(HttpStatus.CREATED) + .status(HttpStatus.OK) .body(ApiResponse.success( - 201, + 200, true, response ));src/main/java/team/wego/wegobackend/common/security/JwtAuthenticationFilter.java (1)
75-75: 코드 스타일: 연산자 사이 공백 누락.
|UserNotFoundException앞에 공백이 없습니다.-} catch (ExpiredTokenException | InvalidTokenException |UserNotFoundException e) { +} catch (ExpiredTokenException | InvalidTokenException | UserNotFoundException e) {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
build.gradle(1 hunks)src/main/java/team/wego/wegobackend/auth/application/AuthService.java(4 hunks)src/main/java/team/wego/wegobackend/auth/exception/DeletedUserException.java(1 hunks)src/main/java/team/wego/wegobackend/auth/exception/InvalidPasswordException.java(1 hunks)src/main/java/team/wego/wegobackend/auth/exception/UserAlreadyExistsException.java(1 hunks)src/main/java/team/wego/wegobackend/auth/exception/UserNotFoundException.java(1 hunks)src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java(3 hunks)src/main/java/team/wego/wegobackend/common/exception/AppErrorCode.java(1 hunks)src/main/java/team/wego/wegobackend/common/exception/GlobalExceptionHandler.java(2 hunks)src/main/java/team/wego/wegobackend/common/response/ApiResponse.java(1 hunks)src/main/java/team/wego/wegobackend/common/security/CustomUserDetails.java(1 hunks)src/main/java/team/wego/wegobackend/common/security/CustomUserDetailsService.java(2 hunks)src/main/java/team/wego/wegobackend/common/security/JwtAuthenticationFilter.java(4 hunks)src/main/java/team/wego/wegobackend/common/security/SecurityConfig.java(1 hunks)src/main/java/team/wego/wegobackend/common/security/exception/ExpiredTokenException.java(1 hunks)src/main/java/team/wego/wegobackend/common/security/exception/InvalidTokenException.java(1 hunks)src/main/java/team/wego/wegobackend/common/security/jwt/JwtTokenProvider.java(5 hunks)src/main/java/team/wego/wegobackend/image/presentation/ImageController.java(4 hunks)src/main/java/team/wego/wegobackend/user/presentation/UserController.java(2 hunks)src/main/resources/application.yml(2 hunks)src/test/http/auth/auth-api.http(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/main/java/team/wego/wegobackend/auth/application/AuthService.java (5)
src/main/java/team/wego/wegobackend/auth/exception/DeletedUserException.java (1)
DeletedUserException(6-11)src/main/java/team/wego/wegobackend/auth/exception/InvalidPasswordException.java (1)
InvalidPasswordException(6-11)src/main/java/team/wego/wegobackend/auth/exception/UserAlreadyExistsException.java (1)
UserAlreadyExistsException(6-11)src/main/java/team/wego/wegobackend/auth/exception/UserNotFoundException.java (1)
UserNotFoundException(6-11)src/main/java/team/wego/wegobackend/common/security/exception/ExpiredTokenException.java (1)
ExpiredTokenException(5-10)
src/main/java/team/wego/wegobackend/common/security/CustomUserDetailsService.java (1)
src/main/java/team/wego/wegobackend/auth/exception/UserNotFoundException.java (1)
UserNotFoundException(6-11)
🪛 ast-grep (0.40.0)
src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java
[warning] 58-58: The application does not appear to verify inbound requests which can lead to a Cross-site request forgery (CSRF) vulnerability. If the application uses cookie-based authentication, an attacker can trick users into sending authenticated HTTP requests without their knowledge from any arbitrary domain they visit. To prevent this vulnerability start by identifying if the framework or library leveraged has built-in features or offers plugins for CSRF protection. CSRF tokens should be unique and securely random. The Synchronizer Token or Double Submit Cookie patterns with defense-in-depth mechanisms such as the sameSite cookie flag can help prevent CSRF. For more information, see: [Cross-site request forgery prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Req\ uest_Forgery_Prevention_Cheat_Sheet.html).
Context: response.addCookie(createRefreshTokenCookie(loginResponse.getRefreshToken()));
Note: [CWE-352] Cross-Site Request Forgery (CSRF). [REFERENCES]
- https://stackoverflow.com/questions/42717210/samesite-cookie-in-java-application
(cookie-missing-samesite-java)
[warning] 79-79: The application does not appear to verify inbound requests which can lead to a Cross-site request forgery (CSRF) vulnerability. If the application uses cookie-based authentication, an attacker can trick users into sending authenticated HTTP requests without their knowledge from any arbitrary domain they visit. To prevent this vulnerability start by identifying if the framework or library leveraged has built-in features or offers plugins for CSRF protection. CSRF tokens should be unique and securely random. The Synchronizer Token or Double Submit Cookie patterns with defense-in-depth mechanisms such as the sameSite cookie flag can help prevent CSRF. For more information, see: [Cross-site request forgery prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Req\ uest_Forgery_Prevention_Cheat_Sheet.html).
Context: response.addCookie(deleteCookie);
Note: [CWE-352] Cross-Site Request Forgery (CSRF). [REFERENCES]
- https://stackoverflow.com/questions/42717210/samesite-cookie-in-java-application
(cookie-missing-samesite-java)
[warning] 58-58: A cookie was detected without setting the 'HttpOnly' flag. The 'HttpOnly' flag for cookies instructs the browser to forbid client-side scripts from reading the cookie. Set the 'HttpOnly' flag by calling 'cookie.setHttpOnly(true);
Context: response.addCookie(createRefreshTokenCookie(loginResponse.getRefreshToken()));
Note: [CWE-1004] Sensitive Cookie Without 'HttpOnly' Flag. [REFERENCES]
- https://owasp.org/www-community/HttpOnly
(cookie-missing-httponly-java)
[warning] 79-79: A cookie was detected without setting the 'secure' flag. The 'secure' flag for cookies prevents the client from transmitting the cookie over insecure channels such as HTTP. Set the 'secure' flag by calling '.setSecure(true);'.
Context: response.addCookie(deleteCookie);
Note: [CWE-614] Sensitive Cookie in HTTPS Session Without 'Secure' Attribute. [REFERENCES]
- https://owasp.org/www-community/controls/SecureCookieAttribute
(cookie-missing-secure-flag-java)
🔇 Additional comments (15)
src/main/resources/application.yml (1)
5-6: 프로파일 활성화 비활성화의 영향 확인 필요Spring 프로파일 활성화를 주석 처리하면 더 이상
local프로파일이 자동으로 활성화되지 않습니다. 이 변경이 의도된 것이라면, 배포 환경에서spring.profiles.active환경 변수를 올바르게 설정하여 필요한 프로파일이 활성화되는지 확인하시기 바랍니다. (예: dev, prod 환경에서 해당 프로파일 명시)build.gradle (1)
44-45: H2가 테스트 환경에서 사용 불가할 수 있습니다.
developmentOnly는bootRun태스크에서만 H2를 포함시키며, 테스트 클래스패스에는 포함되지 않습니다. 통합 테스트에서 H2를 사용한다면 테스트가 실패할 수 있습니다.테스트에서도 H2가 필요하다면 다음과 같이 수정하세요:
// H2 Database - developmentOnly 'com.h2database:h2' + developmentOnly 'com.h2database:h2' + testRuntimeOnly 'com.h2database:h2'src/main/java/team/wego/wegobackend/auth/exception/UserAlreadyExistsException.java (1)
1-11: LGTM!도메인 예외 패턴을 잘 따르고 있으며,
UserNotFoundException등 다른 예외 클래스와 일관된 구조입니다.src/main/java/team/wego/wegobackend/common/exception/GlobalExceptionHandler.java (1)
25-25: RFC 7807 표준에 맞춘 변경입니다.
about:blank는 RFC 7807에서 권장하는 기본값으로, 각 오류 타입에 대한 문서 URL이 없을 때 사용하기 적절합니다.src/test/http/auth/auth-api.http (2)
22-22: 올바른 응답 구조 반영입니다.새로운
ApiResponse구조에 맞춰data.accessToken으로 토큰을 추출하도록 변경되었습니다.
33-50: 유용한 테스트 케이스가 추가되었습니다.토큰이 없는 경우와 잘못된 토큰을 사용하는 경우에 대한 테스트가 추가되어 인증 오류 시나리오를 포괄적으로 검증할 수 있습니다.
src/main/java/team/wego/wegobackend/auth/exception/DeletedUserException.java (1)
6-10: 올바른 예외 구현입니다.
AppException을 확장하고AppErrorCode.DELETED_USER를 사용하여 일관된 예외 처리 구조를 따릅니다.src/main/java/team/wego/wegobackend/auth/exception/UserNotFoundException.java (1)
6-10: 올바른 예외 구현입니다.
AppException을 확장하고AppErrorCode.USER_NOT_FOUND를 사용하여 일관된 예외 처리 구조를 따릅니다.src/main/java/team/wego/wegobackend/auth/exception/InvalidPasswordException.java (1)
6-10: 올바른 예외 구현입니다.
AppException을 확장하고AppErrorCode.INVALID_PASSWORD_VALUE를 사용하여 일관된 예외 처리 구조를 따릅니다.src/main/java/team/wego/wegobackend/image/presentation/ImageController.java (1)
42-42: 새로운 ApiResponse API를 올바르게 적용했습니다.모든 업로드 엔드포인트가 명시적인 HTTP 201 상태 코드를 사용하도록 업데이트되었으며, 이는 생성 작업에 적합합니다. 변경 사항이 일관되게 적용되었습니다.
Also applies to: 60-60, 82-82, 113-113
src/main/java/team/wego/wegobackend/auth/application/AuthService.java (1)
42-56: 도메인 예외 적용 - LGTM!회원가입, 로그인, 토큰 재발급 흐름에서 도메인별 예외(
UserAlreadyExistsException,UserNotFoundException,InvalidPasswordException,DeletedUserException,ExpiredTokenException)로 일관성 있게 변경되었습니다. 이를 통해 예외 처리가 명확해지고 공통 응답 형식과 잘 통합됩니다.Also applies to: 87-110
src/main/java/team/wego/wegobackend/common/security/jwt/JwtTokenProvider.java (1)
105-124: 예외 기반 토큰 검증으로 개선 - LGTM!토큰 검증 실패 시
false반환 대신 도메인 예외(ExpiredTokenException,InvalidTokenException)를 던지도록 변경되어, 호출자가 실패 원인을 명확히 알 수 있고 공통 예외 처리와 일관성이 유지됩니다.src/main/java/team/wego/wegobackend/common/security/JwtAuthenticationFilter.java (3)
37-42: 공개 엔드포인트 필터 스킵 로직 추가.
shouldNotFilter를 통해 공개 패턴에 대해 필터를 건너뛰는 로직이 잘 구현되어 있습니다.
68-70: 인증 성공 시 조기 반환.인증 성공 후
filterChain.doFilter를 호출하고 즉시 반환하여 에러 처리 로직으로 진입하지 않도록 한 것은 좋은 접근입니다.
44-46:ServletExceptionis missing from the throws clause but the code is valid Java.The parent class
OncePerRequestFilterdeclaresthrows ServletException, IOException, but this implementation only declaresthrows IOException. While Java allows an overriding method to declare fewer checked exceptions than the parent (a subset is permitted), removingServletExceptiondiffers from the parent signature. If the try-catch block handlesServletExceptioninternally, this is acceptable; however, if this method could propagateServletExceptionto the caller, it should be declared.
src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java
Show resolved
Hide resolved
| return ResponseEntity | ||
| .status(HttpStatus.NO_CONTENT) | ||
| .body(ApiResponse.success( | ||
| 204, | ||
| true | ||
| )); |
There was a problem hiding this comment.
204 NO_CONTENT 응답에 body 포함.
HTTP 204는 응답 본문이 없어야 합니다. ApiResponse.success()로 body를 포함하면 일부 클라이언트에서 문제가 발생할 수 있습니다.
-return ResponseEntity
- .status(HttpStatus.NO_CONTENT)
- .body(ApiResponse.success(
- 204,
- true
- ));
+return ResponseEntity
+ .status(HttpStatus.NO_CONTENT)
+ .build();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return ResponseEntity | |
| .status(HttpStatus.NO_CONTENT) | |
| .body(ApiResponse.success( | |
| 204, | |
| true | |
| )); | |
| return ResponseEntity | |
| .status(HttpStatus.NO_CONTENT) | |
| .build(); |
🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/auth/presentation/AuthController.java
around lines 82-87, the controller is returning a 204 NO_CONTENT while including
a response body via ApiResponse.success(), which violates HTTP semantics and can
break clients; either remove the body and return
ResponseEntity.noContent().build() for a true 204 response, or if you need to
return ApiResponse.success(...) change the status to 200 (OK) and return that
body instead—update the method to follow one of these two options consistently.
| /** | ||
| * No Content (ex : 204) | ||
| * */ | ||
| public static <T> ApiResponse<T> success(int status, boolean isSuccess) { | ||
| return new ApiResponse<>(status, true, null); | ||
| } |
There was a problem hiding this comment.
isSuccess 파라미터가 무시되고 있습니다.
메서드 시그니처에 isSuccess 파라미터가 있지만, 실제로는 항상 true로 하드코딩되어 있습니다. 이는 혼란을 야기할 수 있습니다.
public static <T> ApiResponse<T> success(int status, boolean isSuccess) {
- return new ApiResponse<>(status, true, null);
+ return new ApiResponse<>(status, isSuccess, null);
}또는 파라미터가 불필요하다면 제거하세요:
- public static <T> ApiResponse<T> success(int status, boolean isSuccess) {
+ public static <T> ApiResponse<T> successNoContent(int status) {
return new ApiResponse<>(status, true, null);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * No Content (ex : 204) | |
| * */ | |
| public static <T> ApiResponse<T> success(int status, boolean isSuccess) { | |
| return new ApiResponse<>(status, true, null); | |
| } | |
| /** | |
| * No Content (ex : 204) | |
| * */ | |
| public static <T> ApiResponse<T> success(int status, boolean isSuccess) { | |
| return new ApiResponse<>(status, isSuccess, null); | |
| } |
🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/common/response/ApiResponse.java around
lines 20 to 25, the method success(int status, boolean isSuccess) ignores the
isSuccess parameter and always passes true to the ApiResponse constructor;
either use the isSuccess parameter when constructing the ApiResponse (pass
isSuccess instead of true) or remove the isSuccess parameter from the method
signature and any callers, and adjust javadoc accordingly so the method behavior
matches its signature.
| public static <T> ApiResponse<T> error(int status, String message) { | ||
| return new ApiResponse<>(status, false, null); | ||
| } |
There was a problem hiding this comment.
message 파라미터가 사용되지 않습니다.
error 메서드에서 message 파라미터를 받지만 응답에 포함되지 않습니다. 에러 응답에서 메시지 정보가 손실됩니다.
에러 메시지를 data 필드에 담거나, 별도의 message 필드를 record에 추가하는 것을 고려하세요:
public static <T> ApiResponse<T> error(int status, String message) {
- return new ApiResponse<>(status, false, null);
+ return new ApiResponse<>(status, false, (T) message);
}또는 ApiResponse record에 message 필드를 추가하세요.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/common/response/ApiResponse.java around
lines 27-29, the error(int status, String message) method accepts a message but
doesn't include it in the response; update the ApiResponse record to carry a
message field (e.g., add String message as a component), update all
constructors/factory methods to set that field, and change this error(...) to
return a new ApiResponse<>(status, false, null, message) (or equivalent) so the
passed message is included; ensure any callers or JSON serialization mappings
are updated to reflect the new field.
| @Override | ||
| public Collection<? extends GrantedAuthority> getAuthorities() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public String getUsername() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public String getPassword() { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
Critical: UserDetails 메서드가 null을 반환합니다
생성자에서 authorities와 email을 올바르게 초기화하지만, getAuthorities()와 getUsername() 메서드가 null을 반환합니다. 이로 인해 Spring Security 인증/인가 과정에서 심각한 오류가 발생합니다:
getAuthorities(): 권한 검사 시 NPE 또는 인가 실패getUsername(): 인증 주체 식별 실패
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
- return null;
+ return authorities;
}
@Override
public String getUsername() {
- return null;
+ return email;
}
@Override
public String getPassword() {
- return null;
+ return null; // 의도적으로 null 반환 시 주석 추가 권장
}getPassword()가 의도적으로 null을 반환하는 경우, 이유를 명시하는 주석을 추가하세요.
🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/common/security/CustomUserDetails.java
around lines 27-40, getAuthorities() and getUsername() currently return null
despite authorities and email being initialized in the constructor; replace
those null returns to return the stored authorities collection and the stored
email respectively so Spring Security can perform authentication/authorization
correctly, and if getPassword() is intentionally returning null, add a clear
comment explaining why (e.g., using token-based auth or credentials not stored
here) otherwise return the stored password field.
| public class InvalidTokenException extends RuntimeException { | ||
|
|
||
| public InvalidTokenException() { | ||
| super(AppErrorCode.INVALID_TOKEN.getMessageTemplate()); | ||
| } |
There was a problem hiding this comment.
예외 계층 구조의 일관성을 유지하세요.
이 예외는 RuntimeException을 확장하지만, 같은 PR에서 추가된 다른 인증 관련 예외들(UserNotFoundException, DeletedUserException, InvalidPasswordException)은 모두 AppException을 확장합니다. 일관성을 위해 AppException을 확장하고 AppErrorCode.INVALID_TOKEN을 생성자에 전달해야 합니다.
다음 diff를 적용하세요:
package team.wego.wegobackend.common.security.exception;
import team.wego.wegobackend.common.exception.AppErrorCode;
+import team.wego.wegobackend.common.exception.AppException;
-public class InvalidTokenException extends RuntimeException {
+public class InvalidTokenException extends AppException {
public InvalidTokenException() {
- super(AppErrorCode.INVALID_TOKEN.getMessageTemplate());
+ super(AppErrorCode.INVALID_TOKEN);
}
}🤖 Prompt for AI Agents
In
src/main/java/team/wego/wegobackend/common/security/exception/InvalidTokenException.java
around lines 5-9, the class currently extends RuntimeException but should extend
AppException for consistency with other auth exceptions; change the superclass
to AppException and modify the constructor to call
super(AppErrorCode.INVALID_TOKEN) so the AppErrorCode is passed to the
AppException base class.
| private final ObjectMapper objectMapper; | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Search for ObjectMapper usage in the JwtTokenProvider file and related contexts
rg -n "objectMapper" --type java -A 2 -B 2Repository: WeGo-Together/WeGo_BackEnd
Length of output: 1719
🏁 Script executed:
cat src/main/java/team/wego/wegobackend/common/security/jwt/JwtTokenProvider.javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 5157
Remove the unused ObjectMapper field
The objectMapper field is injected via @RequiredArgsConstructor but is never used anywhere in the JwtTokenProvider class. Remove the field declaration and the import statement if it's not needed elsewhere.
🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/common/security/jwt/JwtTokenProvider.java
around lines 39-40, the injected private final ObjectMapper objectMapper field
is unused; remove the field declaration and also remove the corresponding import
(com.fasterxml.jackson.databind.ObjectMapper) if it's not used elsewhere in the
file so the generated constructor and imports stay consistent.
| public boolean validateToken(String token) { | ||
| try { | ||
| Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token); | ||
| log.debug("네 되네요"); |
There was a problem hiding this comment.
디버그 로그 메시지 정리 필요
"네 되네요"는 개발 중 작성된 비공식적인 디버그 메시지입니다. 프로덕션 코드에서는 제거하거나 의미 있는 메시지로 변경하세요.
-log.debug("네 되네요");
+log.debug("JWT token validation successful");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| log.debug("네 되네요"); | |
| log.debug("JWT token validation successful"); |
🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/common/security/jwt/JwtTokenProvider.java
around line 108, the debug log "네 되네요" is an informal development message;
remove it or replace it with a meaningful, contextual message (e.g., describe
the action/state being logged such as "JWT 토큰 생성 성공" or "JWT 검증 성공/실패") and
ensure the appropriate log level (debug/info/error) is used; update the log call
accordingly and keep messages in English or Korean consistently with project
conventions.
src/main/java/team/wego/wegobackend/common/security/JwtAuthenticationFilter.java
Show resolved
Hide resolved
| defer-datasource-initialization: true | ||
| hibernate: | ||
| ddl-auto: none | ||
| ddl-auto: update |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, locate and examine the application.yml file
find . -name "application.yml" -o -name "application-*.yml" | head -20Repository: WeGo-Together/WeGo_BackEnd
Length of output: 106
🏁 Script executed:
# Read the application.yml file to see the current configuration
cat -n ./src/main/resources/application.ymlRepository: WeGo-Together/WeGo_BackEnd
Length of output: 2575
🏁 Script executed:
# Check for any deployment configurations or CI/CD files that might handle environment-specific settings
find . -maxdepth 2 -type f \( -name "*.yml" -o -name "*.yaml" -o -name "*.env*" -o -name "Dockerfile*" -o -name ".gitlab-ci.yml" -o -name ".github" \) 2>/dev/null | grep -E "\.(yml|yaml|env)" | head -20Repository: WeGo-Together/WeGo_BackEnd
Length of output: 109
🏁 Script executed:
# Check docker-compose.yml for any environment variable configuration
cat -n ./docker-compose.ymlRepository: WeGo-Together/WeGo_BackEnd
Length of output: 546
ddl-auto: update 설정 검토 필요
Hibernate의 ddl-auto를 update로 설정하면 엔티티 정의에 따라 데이터베이스 스키마를 자동으로 업데이트합니다. 이는 개발 환경에서는 유용하지만, 프로덕션 환경에서는 예상치 못한 스키마 변경으로 인한 데이터 손상이나 서비스 중단을 초래할 수 있습니다.
현재 환경별 설정 파일이 존재하지 않으며, 모든 환경에 동일하게 update 설정이 적용되는 상황입니다. 환경별로 다른 DDL 전략을 적용하시기를 권장합니다:
- 개발(dev):
update또는create-drop - 프로덕션(prod):
validate또는none
다음 중 하나의 방식으로 해결하시기 바랍니다:
- 프로파일별 설정 파일 분리:
application-dev.yml,application-prod.yml생성 - 환경 변수로 제어: 이미 RDS 설정에서 환경 변수를 활용하고 있으므로,
spring.jpa.hibernate.ddl-auto=${DDL_AUTO:validate}형태로 구성
🤖 Prompt for AI Agents
In src/main/resources/application.yml around line 37, the setting "ddl-auto:
update" is unsafe for production; replace the single global update policy with
profile-specific configuration or an environment-controlled value: create
application-dev.yml (dev: update or create-drop) and application-prod.yml (prod:
validate or none), or change the main config to read ddl-auto from an
environment variable (e.g., DDL_AUTO with a safe default like validate) and
ensure your deployment/CI sets DDL_AUTO appropriately.
📝 Pull Request
📌 PR 종류
해당하는 항목에 체크해주세요.
✨ 변경 내용
기존 인증/인가 로직에서 공통 응답 및 예외 처리 적
🔍 관련 이슈
해당 PR이 해결하는 이슈가 있다면 연결해주세요.
#31
🧪 테스트
변경된 기능에 대한 테스트 범위 또는 테스트 결과를 작성해주세요.
🚨 확인해야 할 사항 (Checklist)
PR을 제출하기 전에 아래 항목들을 확인해주세요.
🙋 기타 참고 사항
Summary by CodeRabbit
릴리스 노트
개선사항
테스트
✏️ Tip: You can customize this high-level summary in your review settings.