Skip to content

Conversation

@wlgns12370
Copy link
Contributor

No description provided.

@wlgns12370 wlgns12370 self-assigned this Aug 12, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 12, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@wlgns12370 wlgns12370 merged commit 3faffd9 into prod Aug 12, 2025
5 of 6 checks passed
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @wlgns12370, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 JWT 토큰 만료 및 유효성 검사 오류 처리를 개선합니다. 토큰 만료 시 ExpiredJwtException을 명시적으로 발생시키고, 이를 전역 예외 필터에서 상세한 JSON 응답으로 처리하도록 변경하여 클라이언트에게 더 명확한 오류 정보를 제공합니다. 또한, 다양한 토큰 관련 예외에 대한 응답 형식을 표준화합니다.

Highlights

  • JWT 토큰 만료 처리 개선: JwtTokenProvider에서 토큰 만료 시 CustomRuntimeException 대신 ExpiredJwtException을 직접 발생시키도록 변경했습니다.
  • 전역 예외 필터 강화: TokenExceptionFilter에서 ExpiredJwtException을 포함한 다양한 예외(CustomRuntimeException, 일반 Exception)를 캐치하여, HTTP 상태 코드와 함께 상세한 JSON 형식의 오류 응답을 클라이언트에게 반환하도록 구현했습니다.
  • 토큰 필터 예외 전파: TokenFilter에서 ExpiredJwtException을 명시적으로 캐치하고 재발생시켜 TokenExceptionFilter에서 중앙 집중적으로 처리할 수 있도록 변경했습니다.
  • 리프레시 토큰 오류 코드 변경: 리프레시 토큰 재발급 불가 시 발생하는 오류 코드를 EXPIRED_REFRESH_TOKEN에서 NOT_FOUND_TOKEN으로 변경했습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

이 PR은 토큰 만료 처리를 개선하고 관련 예외 핸들링을 중앙 필터로 옮기는 좋은 변경을 포함하고 있습니다. JwtTokenProvider에서 ExpiredJwtException을 직접 던지도록 변경하고, TokenFilter에서 이를 적절히 처리하여 TokenExceptionFilter로 전달하는 구조는 명확하고 확장성이 좋습니다. TokenExceptionFilter에서 몇 가지 개선점을 발견하여 리뷰 코멘트를 남겼습니다. 중복 코드를 줄이고, HTTP 상태 코드를 표준에 맞게 사용하도록 수정하면 더 완성도 높은 코드가 될 것 같습니다.

.code(ex.getCode())
.build();

response.setStatus(HttpStatus.UNAUTHORIZED.value());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

CustomRuntimeException을 처리할 때 응답 본문의 status 필드에는 ex.getStatus().value()를 사용하면서, 실제 HTTP 응답 상태 코드는 HttpStatus.UNAUTHORIZED.value()로 고정하고 있습니다. 이 두 값은 일치해야 합니다. response.setStatus() 호출 시에도 ex.getStatus().value()를 사용하여 예외에 정의된 정확한 상태 코드가 반환되도록 수정해야 합니다.

Suggested change
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setStatus(ex.getStatus().value());

Comment on lines +46 to +56
ErrorResponse errorResponse = ErrorResponse.builder()
.status(HttpStatus.NOT_ACCEPTABLE.value())
.message("토큰이 만료되었습니다.")
.code("TOKEN_EXPIRED")
.build();

response.setStatus(HttpStatus.NOT_ACCEPTABLE.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
response.sendError(exception.getStatus().value(), exception.getMessage());

objectMapper.writeValue(response.getWriter(), errorResponse);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

만료된 토큰에 대해 HttpStatus.NOT_ACCEPTABLE (406)을 사용하고 있는데, 이는 일반적으로 Accept 헤더와 서버가 생성할 수 있는 컨텐츠 타입이 맞지 않을 때 사용됩니다. 토큰이 만료된 경우에는 인증이 필요하다는 의미이므로 HttpStatus.UNAUTHORIZED (401)을 사용하는 것이 더 표준에 부합하고 일반적인 REST API 설계 관례에 맞습니다. 클라이언트는 401 응답을 받으면 토큰을 재발급 받거나 다시 로그인하도록 처리할 수 있습니다.

Suggested change
ErrorResponse errorResponse = ErrorResponse.builder()
.status(HttpStatus.NOT_ACCEPTABLE.value())
.message("토큰이 만료되었습니다.")
.code("TOKEN_EXPIRED")
.build();
response.setStatus(HttpStatus.NOT_ACCEPTABLE.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
response.sendError(exception.getStatus().value(), exception.getMessage());
objectMapper.writeValue(response.getWriter(), errorResponse);
ErrorResponse errorResponse = ErrorResponse.builder()
.status(HttpStatus.UNAUTHORIZED.value())
.message("토큰이 만료되었습니다.")
.code("TOKEN_EXPIRED")
.build();
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
objectMapper.writeValue(response.getWriter(), errorResponse);

Comment on lines +32 to 69
} catch (CustomRuntimeException ex) {

ErrorResponse errorResponse = ErrorResponse.builder()
.status(ex.getStatus().value())
.message(ex.getMessage())
.code(ex.getCode())
.build();

response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");

objectMapper.writeValue(response.getWriter(), errorResponse);
} catch (ExpiredJwtException ex) {
ErrorResponse errorResponse = ErrorResponse.builder()
.status(HttpStatus.NOT_ACCEPTABLE.value())
.message("토큰이 만료되었습니다.")
.code("TOKEN_EXPIRED")
.build();

response.setStatus(HttpStatus.NOT_ACCEPTABLE.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
response.sendError(exception.getStatus().value(), exception.getMessage());

objectMapper.writeValue(response.getWriter(), errorResponse);
} catch (Exception ex) {
ErrorResponse errorResponse = ErrorResponse.builder()
.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
.message("서버 오류가 발생했습니다.")
.code("INTERNAL_SERVER_ERROR")
.build();

response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");

objectMapper.writeValue(response.getWriter(), errorResponse);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

catch 블록에서 HttpServletResponse에 에러 응답을 설정하는 코드가 중복되고 있습니다. 이 로직을 별도의 private 메서드로 추출하여 코드 중복을 줄이고 가독성과 유지보수성을 높이는 것을 제안합니다. 예를 들어, 다음과 같은 헬퍼 메서드를 만들 수 있습니다:

private void sendErrorResponse(HttpServletResponse response, ErrorResponse errorResponse) throws IOException {
    response.setStatus(errorResponse.getStatus());
    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
    response.setCharacterEncoding("UTF-8");
    objectMapper.writeValue(response.getWriter(), errorResponse);
}

이렇게 하면 각 catch 블록이 더 간결해집니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants