Skip to content

사용자 로그인 풀림 이슈 해결#55

Merged
rktclgh merged 2 commits into
mainfrom
develop
Mar 11, 2026
Merged

사용자 로그인 풀림 이슈 해결#55
rktclgh merged 2 commits into
mainfrom
develop

Conversation

@rktclgh

@rktclgh rktclgh commented Mar 11, 2026

Copy link
Copy Markdown
Owner

📢 기능 설명

필요시 실행결과 스크린샷 첨부

연결된 issue

연결된 issue를 자동으로 닫기 위해 아래 {이슈넘버}를 입력해주세요.

close #{이슈넘버}



🩷 Approve 하기 전 확인해주세요!

  • 리뷰어가 확인해줬으면 하는 사항 적어주세요.
  • [ ]

✅ 체크리스트

  • PR 제목 규칙 잘 지켰는가?
  • 추가/수정사항을 설명하였는가?
  • 이슈넘버를 적었는가?
  • Approve 하기 전 확인 사항 체크했는가?

@coderabbitai

coderabbitai Bot commented Mar 11, 2026

Copy link
Copy Markdown

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.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1e579340-8a87-411e-9ca3-c059600dd3bf

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • 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

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, 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은 사용자 로그인 세션 관련 문제를 해결하고 API 응답의 일관성과 보안을 강화하는 데 중점을 둡니다. 시간대 설정을 통일하여 잠재적인 시간 관련 오류를 방지하고, 사용자 ID 노출을 최소화하여 보안을 개선했습니다. 또한, 카테고리 관리 API의 응답을 사용자 역할에 따라 분리하여 데이터 접근 제어를 명확히 하고 코드의 가독성을 높였습니다.

Highlights

  • 시간대 설정 일관성 확보: 애플리케이션 시작 시 기본 시간대를 'Asia/Seoul'로 명시적으로 설정하고, Jackson 직렬화/역직렬화에도 동일한 시간대 설정을 적용하여 시간 관련 불일치로 인한 사용자 로그인 풀림 이슈를 해결했습니다.
  • 응답 DTO에서 사용자 ID 제거: 로그인, 회원가입, 사용자 프로필, 사용자 파일 응답 DTO에서 userId 필드를 제거하여 API 응답의 데이터 노출을 최소화하고 보안을 강화했습니다.
  • 카테고리 API 응답 분리 및 리팩토링: 카테고리 관련 API 응답을 일반 사용자용(PublicCategoryResponse)과 관리자용(AdminCategoryResponse)으로 분리하고, 관련 컨트롤러 및 서비스 로직을 리팩토링하여 역할에 따른 데이터 접근 제어를 명확히 했습니다.
  • 리프레시 토큰 유효성 검사 로직 개선: 유효하지 않은 리프레시 토큰 처리 시 loginSessionStore.delete 호출을 제거하고, refreshUnauthorizedException이라는 더 구체적인 예외를 발생시키도록 AuthService의 로직을 변경했습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/main/kotlin/com/cw/vlainter/VlainterApplication.kt
    • java.util.TimeZone를 임포트했습니다.
    • 애플리케이션 시작 시 기본 시간대를 'Asia/Seoul'로 설정했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/auth/controller/AuthController.kt
    • 회원가입 성공 응답에서 userId, email, name 필드를 제거하고 message만 반환하도록 변경했습니다.
    • 현재 사용자 정보 조회 응답에서 userId 필드를 제거했습니다.
    • 로그인 응답에서 userId 필드를 제거했습니다.
    • 소셜 로그인 응답에서 userId 필드를 제거했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/auth/dto/LoginResponse.kt
    • LoginResponse 데이터 클래스에서 userId 필드를 제거했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/auth/service/AuthService.kt
    • 유효하지 않은 리프레시 토큰 처리 시 loginSessionStore.delete 호출을 제거했습니다.
    • 새로운 refreshUnauthorizedException을 도입하여 인증 만료 메시지를 제공하도록 변경했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/interview/controller/InterviewAdminController.kt
    • CategoryResponse 대신 AdminCategoryResponse를 사용하도록 임포트 및 메서드 반환 타입을 변경했습니다.
    • 카테고리 조회, 생성, 업데이트, 이동, 병합 메서드의 반환 타입을 AdminCategoryResponse로 변경하고, 관련 서비스 메서드를 getActiveCategoryTreeForAdmin, createCategoryForAdmin 등으로 업데이트했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/interview/controller/InterviewCatalogController.kt
    • CategoryResponse 대신 PublicCategoryResponse를 사용하도록 임포트 및 메서드 반환 타입을 변경했습니다.
    • 카테고리 트리 조회 및 생성 메서드의 반환 타입을 PublicCategoryResponse로 변경하고, 관련 서비스 메서드를 getActiveCategoryTreeForUser, createCategoryForUser 등으로 업데이트했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/interview/dto/CategoryDtos.kt
    • CategoryResponsePublicCategoryResponseAdminCategoryResponse 두 개의 데이터 클래스로 분리했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/interview/service/CategoryAdminService.kt
    • CategoryResponseAdminCategoryResponsePublicCategoryResponse로 대체하도록 임포트를 변경했습니다.
    • 사용자 및 관리자용 카테고리 트리 조회 메서드(getActiveCategoryTreeForUser, getActiveCategoryTreeForAdmin)를 분리하고 각각 PublicCategoryResponseAdminCategoryResponse를 반환하도록 했습니다.
    • 카테고리 생성 로직을 createCategoryInternal 메서드로 추출하고, 사용자 및 관리자용 생성 메서드(createCategoryForUser, createCategoryForAdmin)에서 이를 호출하도록 변경했습니다.
    • 카테고리 업데이트, 이동, 병합 메서드의 반환 타입을 AdminCategoryResponse로 변경했습니다.
    • toResponse 헬퍼 함수를 toPublicResponsetoAdminResponse로 분리했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/user/dto/UserProfileResponse.kt
    • UserProfileResponse 데이터 클래스에서 userId 필드를 제거했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/user/service/UserService.kt
    • toProfileResponse 헬퍼 함수에서 userId 필드를 제거했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/userFile/dto/UserFileResponse.kt
    • UserFileResponse 데이터 클래스에서 userId 필드를 제거했습니다.
  • src/main/kotlin/com/cw/vlainter/domain/userFile/service/UserFileService.kt
    • UserFileResponse 생성 시 userId 필드를 제거했습니다.
  • src/main/resources/application.properties
    • spring.jackson.time-zone=Asia/Seoul 설정을 추가하여 Jackson 직렬화/역직렬화 시 시간대 일관성을 확보했습니다.
  • src/test/kotlin/com/cw/vlainter/domain/auth/controller/AuthControllerTests.kt
    • 회원가입 테스트에서 응답 JSON에 userId가 존재하지 않음을 확인하도록 변경했습니다.
  • src/test/kotlin/com/cw/vlainter/domain/auth/service/AuthServiceTests.kt
    • 리프레시 토큰이 유효하지 않을 때 세션 삭제 로직이 호출되지 않음을 확인하도록 테스트를 수정했습니다.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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.

@rktclgh rktclgh merged commit 05a0e8b into main Mar 11, 2026
2 of 3 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Vlainter_BackEnd Mar 11, 2026

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

이번 PR은 타임존 설정을 명시적으로 지정하고 리프레시 토큰 처리 로직을 개선하여 사용자 로그인 세션 유지 문제를 해결하는 중요한 변경을 포함하고 있습니다. 또한, 여러 DTO에서 userId를 제거하고 사용자용/관리자용 DTO를 분리하여 API 응답의 보안을 강화하고 코드를 리팩토링한 점이 인상적입니다. 전반적으로 좋은 변경이지만, 리프레시 토큰 처리 로직 변경에 따른 보안적 측면과 JVM 기본 타임존 설정 방식에 대해 몇 가지 제안 사항을 리뷰 코멘트로 남겼습니다. 확인 부탁드립니다.

Comment on lines 177 to 179
if (!validSession) {
loginSessionStore.delete(sessionId)
throw unauthorizedException()
throw refreshUnauthorizedException()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

리프레시 토큰 검증 실패 시 세션을 삭제하지 않도록 변경하면 여러 탭/기기에서의 사용자 경험이 향상될 수 있습니다. 하지만 이는 보안상 중요한 '리프레시 토큰 재사용 탐지' 기능을 약화시킬 수 있습니다. 토큰 회전(rotation) 전략에서 이전에 사용된 토큰이 다시 등장하는 것은 토큰 탈취의 강력한 신호로 간주됩니다. 이 경우, 보안 강화를 위해 해당 세션을 즉시 만료시키는 것이 좋습니다. 기존의 loginSessionStore.delete(sessionId) 로직이 이러한 방어적 역할을 수행했습니다. 현재 변경은 사용자 편의성을 높이지만, 잠재적인 보안 위협을 탐지하고 대응할 기회를 놓칠 수 있습니다. 사용자 경험과 보안 사이의 균형을 고려하여 이 변경 사항을 재검토해 보시길 권장합니다.

class VlainterApplication

fun main(args: Array<String>) {
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

JVM의 기본 시간대를 main 함수에서 직접 설정하는 것보다 Spring의 생명주기에 맞춰 관리하는 것이 더 좋습니다. 설정을 중앙에서 관리하고 테스트 용이성을 높이기 위해, 이 로직을 @SpringBootApplication 클래스 내부에 @PostConstruct 어노테이션을 사용한 초기화 메서드로 옮기는 것을 고려해 보세요. 이렇게 하면 애플리케이션의 진입점(entry point)을 더 깔끔하게 유지할 수 있습니다.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 858d7b4f6a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 177 to +178
if (!validSession) {
loginSessionStore.delete(sessionId)
throw unauthorizedException()
throw refreshUnauthorizedException()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Revoke session when refresh validation fails

When validateRefreshToken returns false, this branch now just returns 401 and leaves the Redis session alive. In the replay/hijack scenario (an old refresh token is reused after rotation, including a stolen token), the session remains valid for whoever holds the latest refresh token, so the anomaly no longer forces containment. Previously deleting sid here revoked the whole session family; removing that revocation weakens token-theft recovery behavior.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant