Skip to content

Conversation

@seung-in-Yoo
Copy link
Member

@seung-in-Yoo seung-in-Yoo commented Jul 17, 2025

#️⃣ 연관된 이슈

#41

📝 작업 내용

  1. 회원가입/로그인 구조 개선
  • email + loginType 조합을 복합 unique로 처리
  • User 엔티티 및 DB 테이블 unique 제약조건 반영
  • UserRepository/JPA 쿼리 email+login type 방식으로 수정
  • 회원가입/로그인 (email+loginType 중복 체크 및 조회로 개선)
  • API 요청 DTO에 loginType 추가
  1. JWT 인증/보안 리팩토링
  • JwtAuthenticationFilter에서 토큰 미인증/실패시 SecurityContext 초기화(보안 강화)
  • JwtTokenProvider에서 토큰 유효성 먼저 검증
  • email+loginType 복합 unique 인덱스 추가(중복 계정 허용/차단 정책 반영)

💬 리뷰 요구사항 (선택)

refreshToken 관련 로직은 이후에 확장 및 구현하겠습니다!

Summary by CodeRabbit

  • 신규 기능

    • 로그인 요청 시 로그인 유형을 명시적으로 선택할 수 있도록 필드가 추가되었습니다.
  • 버그 수정

    • JWT 토큰이 유효하지 않거나 Authorization 헤더가 없을 때 보안 컨텍스트가 명확하게 초기화되어 인증 상태가 잘못 유지되는 문제를 방지합니다.
  • 개선 사항

    • 이메일과 로그인 유형의 조합으로 사용자 중복 및 조회가 이루어지도록 변경되어, 동일 이메일로 여러 로그인 유형을 사용할 수 있습니다.
    • 사용자 테이블에 이메일과 로그인 유형의 복합 유니크 제약 조건이 적용되었습니다.
    • JWT 서명키의 캐싱 및 토큰 검증 로직이 개선되었습니다.
    • JWT 토큰의 식별자가 이메일에서 사용자 ID(Long 타입)로 변경되어 보안 및 관리가 강화되었습니다.

@seung-in-Yoo seung-in-Yoo requested a review from KiSeungMin July 17, 2025 17:18
@seung-in-Yoo seung-in-Yoo self-assigned this Jul 17, 2025
@seung-in-Yoo seung-in-Yoo added 🔧 refactor 코드 리팩토링 🛠️ fix 기능 오류 및 코드 개선이 필요한 곳 수정 labels Jul 17, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 17, 2025

## Walkthrough

이 변경 사항은 사용자 인증 및 회원가입 로직에서 이메일과 로그인 타입의 조합으로 사용자 고유성을 검증하도록 전체적으로 수정했으며, JWT 인증 필터와 토큰 제공자의 보안 컨텍스트 처리 및 키 캐싱 로직도 개선되었습니다. 또한, 로그인 요청 DTO에 로그인 타입 필드가 추가되었습니다.

## Changes

| 파일/경로 요약 | 변경 내용 요약 |
|---|---|
| .../jwt/JwtAuthenticationFilter.java, .../jwt/JwtTokenProvider.java, .../jwt/JwtAuthentication.java | JWT 인증 필터가 토큰이 유효하지 않거나 헤더가 없을 때 보안 컨텍스트를 명시적으로 초기화하도록 수정, JwtTokenProvider에서 서명 키 캐싱 및 토큰 유효성 검사 강화, JwtAuthentication 클래스가 이메일 대신 userId(Long)를 주체로 사용하도록 변경 |
| .../user/dto/UserLoginRequestDto.java | 로그인 요청 DTO에 `@NotNull`이 적용된 `loginType` 필드 추가 |
| .../user/entity/User.java | User 엔티티에 이메일과 로그인 타입의 복합 유니크 제약 조건 추가, 이메일 단일 유니크 제약 삭제 |
| .../user/repository/UserRepository.java | 이메일 단일 쿼리 메서드 제거, 이메일+로그인 타입 조합 쿼리 메서드로 대체 |
| .../user/service/UserService.java, .../user/service/auth/AuthService.java | 사용자 중복 체크 및 로그인 시 이메일+로그인 타입 조합으로 사용자 조회 방식 변경, JWT 토큰 생성 시 이메일 대신 userId 사용 |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant AuthService
    participant UserRepository
    participant JwtTokenProvider

    Client->>AuthService: login(email, password, loginType)
    AuthService->>UserRepository: findByEmailAndLoginType(email, loginType)
    UserRepository-->>AuthService: User or NotFound
    AuthService->>JwtTokenProvider: generateToken(userId, role)
    JwtTokenProvider-->>AuthService: JWT Token
    AuthService-->>Client: TokenResponseDto

Possibly related PRs

Suggested reviewers

  • KiSeungMin

Poem

🐇
이메일만으론 부족했지,
로그인 타입 곁들여야 진짜지!
JWT 키는 캐싱하고,
컨텍스트는 깨끗하게 비우고,
로그인 요청엔 타입을 꼭—
토끼는 오늘도 깡총깡총,
코드가 더 안전해졌지롱!


<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6adb7502bb3f23700879833aa3d91fcf27922eb4 and b7af73702590895700e5c3f9662aee8b788dfbcf.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java

</details>

</details>
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpETZWaCrKNxU3bABsvkCiQBHbGlcABpIcVwvOkgAIgBtfwAzNDF8CgBdSEAdDsAP2sAPcYB6QBi1wAWxwAAawFDxyEAbWsAQNchAAFrACg7IQBrOwEplwALFwEHOyEARycBI1dDY+2wBZnUaejlIbERKexJsDCIweAwwAE18fHCk/AZ56X4sZNSCCg2iCNgSSC98Ig30DHp/Z8RcKnF8LHhmNxomwMLhqPA/igsLg7pAAOpoWQCaKQADKvGuPAo+BEYg0MFhDFgmFIyDQtFo/kQyCQDnuZgALABGV70DYMLzYJS3e4HHz4ADumIA1iR5NhuLRqNIOEYmfiAJKA7FSEG4ZAEHn2eBEDASwqPZ5YL4UbBibD+WWQa1QOD3JjMNQYcGQ/BJSAkZjaXyYeiGjbQWTce6oDCCyDEt7RehoMkKQH4RDqe4reBBe1/E3aUEaAzW3QE+4AVQWfHY6nkvoUFCp3D+tExUrBAlj92bKOJUkgAhIZDmkul9E1yWiYluqFT6YUGCzG00eZtkBLlBsJDrSculbekAAUlYAIKQdNXE6d+49vvMRTwJLwGKa45az3eyAAageTwDQYzjo2Lowub5lAqI6nq3Csh+RpYoc0gLMgYYCjwlAHBQzCQLQEpePADDSowdwMMKZLbo8+DChKMitvQkLPvAPrEZ+GCBsGgGLnakD7lYCp+IEwRfJAAAi0AAPLIGe3a9lgEpNve+BQhyXJtrC/qMd+kC3iQXi0LmBgAEz4jucLQDgMLljhvxYFWCxHFcuDyOcaRXKsVqsbCO4Crg+54HcoLYf+ABitE0HwCGMNEzgarCqKiBaFYAMJ/DQAAeuCQAK3kRKRfZoF5pn/mp3rIOkKDIJM1LXOEZCRgwmJWTFtksQWbm4NAmUYFYKrwEofASGgWHSRqrWQD1fUVuJKH3PgJl8PgwY/BCM4NVAh4OuuyZzBgabBFCSiJacHperRb6QV+wYRrG4lZRSMkehgKEMPcdZYdVJyQhhQK+TQ6AMEwKzqtpbHZTCRVhjQEXUNxSRUrALWips/heIOx0MKltG+D2HqJdwvoxFWAJAp67AxC8SR4BaKYDqD+JsZ4PjcemfHaMwA0oMq+BdiZfiCPMuDkNSEG1TZ8hulqgPeeIZnzfYshfJ63Z2SQt4bas62bRmM7fNm6oQQQsNnVGmJsESmBIEz2n6MY4BQGQVHuoDhCkOQPwxA6apcLw/DCKI4hSDI8hMF1KhqJo2i6GAhgmLaCA0kRxn22QyjTPGrt+GgiEOE4LhywoAeqOoWg6ObFumAYiAUAwhQHRghRCGgPWFA6hQCoiyIkIUpZSBQ9csFeVdMLdOpt9FgvV+5hRNZ5Jk+RLfwBV4QUaDXPWyrEK8GBY7EKsQ8dO/Q6depnwtG6s0huLCt5z4s/rIy8AAGtD4LPQUKqClDOl4N+pedV4NupQ6yf4QJUj3BIMlKgYhJbCw5scCgAByZANFfCQxYFqAyRkdZ9iFDCDGGtwGundFA0scDIAKn4ugOMN8AAyfwiAf2GsEcIaVsKwGKjySSCw/6MH8LhDmN9x45Snv+D+ghcSaHYhSdQ81epeFkBVTGT11CMCkczG+UVrJxQSiA3AAAJfAmlKAaA5CQZw8UX7JQABQAEoP4CkoPcckSg2TQgFLJHCcEuBpT7BzVBGVdaoA2MNTqEEPHQlhBPWA6R4AAC88p3HJIsVApUkzKyKvfE4IN7BggoClTBzDYgACEjH+D4LEKmUcboOCpFqAWo0+5JRSqgQxzgYjBJIB3YyYsPqSxwhgdJ6MQgqCwogO4WlzCWH3BfOamYMpaiUByZw/5CruhAXWLJMQiqeGRNhG6kQ7yICMAAOT+CQXMK9YhGAgGAIwpdy6V2rrXNAXdmCN2btEQeFAO6PJ7l3fuRBB5qNsiPXAY93IwzIO1NmnV9GLzQMvVe699ybwdgnGIe9nBC3dEfUkp97i8JBa1cFEhIUUA/nMvmTdkD2UuNdDYEjepRLsduL46RFL3CTLqEUYpTj3ShOgNSf5EF3k0pAG+bKlZEAANJig/hhRyNw+4mjNOZcIACEbVWVhzXgrSITzAeGgSJ8g2BA3oDfUguAQLstWJK2Qlib6lLVgqhykAQrLPkVEP2fwO5aw5lZfwKVNRFmgH5MAAAOOWoM1JFVFPIJFkyAKFmFTG6UoKMAf0NeE2gRDbwUD4ljKghrFiYpiEgtCKjviYgQR/TUlDqFzFLAqWgN9whVg5ug404wREsIWH62S3qy3KwAVSdgeVhY32gfWj+GwZbkn4Esg6XgqaDVFZiKsASmySxCo+DmOEiQxBFaBa4VqP7qU0narEWr8A6pNSQXAABROdZjUR9puK2qxkA02KE/hSz0bMcbbhVUAmY8gr24GXBQetD6n0+LIFYhhCAiR8uzSlVd0oIptkGs22A2IBQxxvgqHwJAiC9X3BQIgjh2A3sSvdbg5kJ3un8XS2g4RJ48HCicKsvqLQziqe2r2ZDeXVtWB/MdIy15jImQs6ZHNZkI1jYsjGKzE7rPGE9bZEiT4GCWldeg8rviKqKjfDZKmmrJoJUSsxTVwWzXECcIQ7lLOUGs4gV9LxSXIFxc1fFHUuoTqwCKsuFdsx3Lrg3JuSJXnt0oJ8v43zby/OqQC2zQLjOeYhV1Be9yb4abEQ4rEkhcKK16nyjSxqrXagtRKqVPLXPCuS7DUz3meV+ZuYF6FjznlhdbhFzuLtot91i38uqshAXAo83VrzUKMtZYALLXl/m+696ayvOlwGTYVhmtmPtlZARNNBk0Qa2wg8Im3MTYmiK+wASYRreUxtyDO2SB7aocrYTR3IOnZIM5rA1X3MmfG8SrLq4rxSHoO+4163kbHeVqau93p9uYhfT50KsY3O1bBb9zLmmcsg6u5s5Gj2bimtA+BiHz7WofcR3zb7KXCXeYMKc85xdrkBY2EFh5IWXmdcoB86BhRaAEEKKBqhRpVz01wPxAg6Wl607hWMxF29EaooPhiyMWKDBsRvgLhiwveKi4IB/fwTAKD0HJdg62MRZj2OXU6kgiFj3GuUkxEgQj8GqWrUaB3tqCShmt0VoVqBMAg0Rjk4VAABQ5uB9neHftMsgd1FLgzQMdaEqlmDc3EtBanMQZWYmQ+ZU9eN0gpRQsKwXJ1Hfa1hDfMPEefAf395NPKNj/DoC8IgWS9i6D4kOfwKaPvaCFW6gxvKOmqBzmQI3+438bx3hE6M9i4nzLMyk6IGTEnhbLIL2svgYPVOOfOdlnGVubeCuNSXlSp17ffmseoZhN9Q+TWr1HnPktNQauu8jfX6RjUa6FzxEIYv8AI5NZM5VytZs4dZvJc6lg8587f4bBa5/7i7Qq2pS5nIaYM7+a3KgEsDtYtwQGRbc7lgAqgYS4wooGiYbxbyOzy6OD7zop4QkjqZq6gYfyEF+wIxkpfyzbT7R63TpDcoJ4rSJhrSTjBC8zIDD6ax7RbosBOjDrug3wVoQQ3zKQAD6tkwYtefqsITYKgrYEQAy9w0QUgaMlY4iysCeo6G06YJis4oIiAmhZaAgeAaGWot+0ABhtePS9euekAJi1k/goI0iTGFeihtuRCt+8UnIzAKarwAe5kn69Bx8HC/ggOLKwqIh9wAAvBEKaGXtQI4c4cqgrKOOIOqsSClBkWISws6rwWXDEEIPgHONIijFgsoQxGoZfinD3jCJgHtAoXOrXo8OQNpPCvPvNIvtocvvMgvjOvJhvlRFvm/jvrsnvvuF4WCPEVJIOFwG4QYWYs6GwJANkbENArEBdiHu4S3PsWgIcccaceEBkTYRrKPkcZAMHkWFYcEE8SPqCGYkwFERgPsjcScNkQAN6xAIKxDhCxCqHqEkCxAAC+Fir6kIX2zBjWjOmB9ybWoWuBXWhQBBPkRBpYJB6O7E6xeUWx0wOxwekRjgGA+xkeBhrxKQLeJADxnxWRORwQ5xERui9JjJPgzJ2RrJCwKJWAtuwqihLm7Bbm6Jt8mJLW2JYBeJnO+BUBrB/OJJSBZBaBlyJcGBSpwW2BuJ4Wapnc3OACQhm4WpK4a41p6QsgJBsKZy8KsuVBicCudBhaeyqusIVpG4jpUIQUKQ3K6upYq4q0m41inBP83Bw4a4qqE+C2igYMKUx43B0CyAre0QzRswCCLRzCIOaZR4wQmcswAgk0zCBZVYykEQ34+I6IogU+OEPgMiWoWON8istAeSsg0OtEsOysCCr6xuKRP6MYf6iZAGhZwq3ZvZ/ZXgaxtAp+Dug5Nwh2kAK5qkF+wYVijZAItEzgQRUpiUSA6o8596xO+03oI550/690gGJ5Z5iAF53oS5W5wYa515tE4QH5hhDEDue5nu4hyudiFIMcFu5khWuawJQUxeAFnRL+sIx4BqKZfeRRiscOsI0CH4pEEonCyYVwCemo7InI3IdZcJze1CSY3ICC2ks+4yQUEmSF9w0m0x4xsx6+qyCxPASxhBKx02aFS21Aq2VJdAOxQk1GkiXgwAoGegfKbwr5A5V5w5H8l2N8klUFMlclClPZfZc675CFn5Klc6v5Rl/5bu34ZOc4yEQCwqoGkZDpLggBipzOWBTyppHO7y6pkWAZ6gjptpFAjlgZLgpJglRqwlK2TeYltAOxlZuiRiWAICz5SlXgX5qlkA6l8VYUSVp5XwL5+lb5bwf56Vplm55liegFCONlFAoZOKDl9pIVsgLlhpblypJp7OeBFpUBflNpDVUZjpYVdOepVyrVIB7VHlnV+J3O7c2ErcoGUU7yc1zpZBbplByKu8NBaKsxPp2Ktaiwoq+FIORCb0T0uEOFO6BECRha9AxaQ0lAN4sg5aeVNAGA3K+Zc6VF5A0yHcj1z1Z5ZA718glZWCNZ9EUEcJpSCSXBJwUCnJVREhc40y8qRKWoFFqkLwkFz+PasIBZwS6E16lAkwYqKAts+1fAvUXCtA8gyV+VwRtiswyQNKZRasDY8RPRfqVwRApA2aWoJxpYzeVNNNL1iAowICVGueRgDFYxUyLFBNcysmnFmM8x/AixOOyx6mUAXePpkmsIoqIllSa+yt3FqtvF6t/F0gAA3B2UJXurqBKGYg1Z8EFPAV8P/nTK+ikdmMgCsDdTyvrVFeyacM0eoDSC/BQG/EjAkZPr/CcqvCNQac1m1caZNeAdNVAbNfdIUKLIUGEotYSvdCtXTmtXdptRnN6aBb6WxHWVji8BzHnZznNeTmPudDFdMihVqDhb1UGRWVWd+XRH6AxPWadPMJiF2RsHpQuYZZZRoVCFOjbMHcDTTZ9UHuPYpYVbRB7vuOIlpceV4oZFBlgDtuuuGMcKhuTUQhkcQqQmYqOiSaauBlYhYnxt6jxmOJOjQNOpAthYQvAp9bfdAhoFDvek/aeljNSM4obvdVcLeNPBZNuOLWuPEZGLQFhP2jRJJG9aBSJqMUxTMXLWxYrUbQppvmbSphbb6VrS4pXbrayqBAbS9EssbYpmreQ0SbstbRzJ2dvsmquIgHWDOCQO7cpI7aWKfq7Trv/IEJ7Rgz7VgwwY4pFWTHHagRcqNUneNSnTgWad5d1t3L1n8P1vFkNoliNmErlLntCi6eQQiutTvGMOXTtZXXtV9nwpPOLIItHTDckVOdyhqo5NVFjL4JCj5OpHwHdRYSZd6JWm3vBU9nWg2qesPnplvvMvmhTduNITWNIAIw2MrBiD1J9JKePokaQDGN9J/tcNIqej+jWJ1EoL5qau1OyPAEEzavNhFSFBxhHefXfZQOOnPZ/QvTwhWqelSClN/faLKeEKRVyFhfcEQFQC/DGF5BErZBBKLBY5LF8CJYgEUZXHIzdfRTYzLVxgQ1MUQ0wyQzxdvhQ3vt8Sk0o9FRTOJTVu5OYwIuZKVTeWpW8x5Pwh4183juTfWmTq4+8wC50n8C1RoyzjiVNeaVFr3IYwPMY8Nm4x0nA2FVAAFMVsPQyvQAceTNJLFWtlcIU7yPymiJBooepQU/llS8C8JgjuC/8+41CzEQqWNXCyqTox8j1siz8gNsPKYxi1s38Ni5AFNkJQHaJfI0kd2HgNxFFUnqdAsF6FPCBQozsdvkJJ7GOE0wE6071O0109epxm5sy5AGYnjs/R/UYgvf0dE9a8Tna59rKX8x84C/NDC8ATyx1WnYiwKzFqi0PBWOixC+y1izqcNYXBHDdAvXbHY4jC7OwFwFQGnFteWe6jnEHPnKHOHJbEnOoCoZ1IgCof4IStbnQCoTs1kgW0XFALQAAGwADMAgtAwarbSQtArbTIAADIOzpN9AAOwMB9u0AMhJA6TNskAACcPbPbaATIaAKQs7zbDb8bzb5IAgI7AArP2zpKoN2zpK2yO4O8GiO3O12622gGgK27QHO0yEkAwNO1ezpDpCQAIAyJu0W7u6uyO2e4e3u3O/28GnO3u+e/2yQHu+O0kHO8282zpGgL2MGru8GsGrQEkAIK+w2wYPGy7CW2WxW1qtW7QCodbAW0AA== -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Wayble-Project/wayble-spring&utm_content=51):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `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. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- 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 src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### 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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java (1)

44-50: 토큰 유효성 검증 개선이 보안을 향상시킵니다.

명시적인 토큰 검증을 통해 fail-fast 동작을 구현한 것은 좋은 보안 개선사항입니다.

다만, validateToken()이 두 번 호출되는 중복을 최적화할 수 있습니다:

 public String getEmail(String token) {
-    if (!validateToken(token)) {
-        throw new IllegalArgumentException("Invalid token");
-    }
-    return Jwts.parserBuilder().setSigningKey(getSigningKey()).build()
-            .parseClaimsJws(token).getBody().getSubject();
+    try {
+        return Jwts.parserBuilder().setSigningKey(getSigningKey()).build()
+                .parseClaimsJws(token).getBody().getSubject();
+    } catch (JwtException | IllegalArgumentException e) {
+        throw new IllegalArgumentException("Invalid token");
+    }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6d3415 and d63bd83.

📒 Files selected for processing (7)
  • src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java (1 hunks)
  • src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java (2 hunks)
  • src/main/java/com/wayble/server/user/dto/UserLoginRequestDto.java (2 hunks)
  • src/main/java/com/wayble/server/user/entity/User.java (2 hunks)
  • src/main/java/com/wayble/server/user/repository/UserRepository.java (1 hunks)
  • src/main/java/com/wayble/server/user/service/UserService.java (1 hunks)
  • src/main/java/com/wayble/server/user/service/auth/AuthService.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/main/java/com/wayble/server/user/entity/User.java (1)
Learnt from: seung-in-Yoo
PR: Wayble-Project/wayble-spring#37
File: src/main/java/com/wayble/server/user/entity/User.java:61-62
Timestamp: 2025-07-13T15:08:59.288Z
Learning: Java에서 같은 패키지 내의 클래스들은 import 구문 없이 서로를 참조할 수 있다. com.wayble.server.user.entity 패키지 내의 클래스들은 명시적인 import 없이 사용 가능하다.
🔇 Additional comments (13)
src/main/java/com/wayble/server/user/dto/UserLoginRequestDto.java (2)

3-3: 새로운 import 구문 추가 확인

LoginType과 @NotNull import가 적절히 추가되었습니다.

Also applies to: 6-6


17-21: LoginType 필드 추가 및 검증 로직 확인

로그인 타입 필드가 적절한 검증 어노테이션(@NotNull)과 함께 추가되었습니다. 이메일과 로그인 타입의 복합 고유성 제약 조건을 지원하기 위한 변경사항이 올바르게 구현되었습니다.

src/main/java/com/wayble/server/user/service/UserService.java (1)

21-21: 복합 고유성 제약 조건을 위한 중복 검사 로직 업데이트

이메일과 로그인 타입을 함께 고려하여 사용자 중복을 검사하도록 변경되었습니다. 이는 전체 리팩토링 목표와 일치합니다.

src/main/java/com/wayble/server/user/service/auth/AuthService.java (1)

23-24: 로그인 로직에서 복합 키 사용으로 업데이트

이메일과 로그인 타입을 함께 사용하여 사용자를 조회하도록 변경되었습니다. 이는 새로운 복합 고유성 제약 조건과 일치합니다.

src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java (2)

32-35: 토큰 검증 실패 시 보안 컨텍스트 클리어 로직 추가

유효하지 않은 토큰에 대해 명시적으로 SecurityContext를 클리어하는 로직이 추가되었습니다. 이는 보안을 강화하는 좋은 개선사항입니다.


36-39: Authorization 헤더 부재 시 보안 컨텍스트 클리어 로직 추가

Authorization 헤더가 없거나 Bearer 토큰이 아닌 경우에도 SecurityContext를 클리어하도록 개선되었습니다. 이는 잠재적인 보안 취약점을 방지합니다.

src/main/java/com/wayble/server/user/entity/User.java (3)

21-24: 복합 고유성 제약 조건 데이터베이스 레벨 구현

email과 login_type의 복합 고유성 제약 조건이 @table 어노테이션에 올바르게 추가되었습니다. 이는 데이터베이스 레벨에서 중복을 방지하는 효과적인 방법입니다.


36-37: 이메일 필드의 개별 고유성 제약 조건 제거

이메일 필드에서 unique=true 속성이 제거되었습니다. 이는 복합 고유성 제약 조건으로 변경되면서 적절한 수정사항입니다.


21-24: UserRepository 메서드 일관성 확인 완료

  • UserRepository 인터페이스에 existsByEmailAndLoginType, findByEmailAndLoginType 메서드가 구현되어 있습니다.
  • AuthService와 UserService에서도 해당 메서드를 사용 중이어서 엔티티의 복합 고유 제약 조건(email + login_type)과 일치합니다.

추가 조치가 필요 없습니다.

src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java (2)

16-16: 성능 최적화를 위한 키 캐싱 필드 추가가 적절합니다.

서명 키를 캐싱하여 매번 재생성하는 오버헤드를 줄이는 좋은 개선사항입니다.


18-23: 스레드 안전성 문제를 검토해 주세요.

지연 초기화 패턴이 올바르게 구현되었지만, 멀티스레드 환경에서 동시 접근 시 경합 조건이 발생할 수 있습니다.

다음과 같은 해결책을 고려해 보세요:

-    private Key getSigningKey() {
-        if (signingKey == null) {
-            signingKey = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes());
-        }
-        return signingKey;
-    }
+    private synchronized Key getSigningKey() {
+        if (signingKey == null) {
+            signingKey = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes());
+        }
+        return signingKey;
+    }

또는 더 효율적인 double-checked locking 패턴을 사용하거나, @PostConstruct를 사용하여 초기화를 고려해 보세요.

src/main/java/com/wayble/server/user/repository/UserRepository.java (2)

3-3: LoginType 임포트 추가가 적절합니다.

새로운 메서드 시그니처에 필요한 올바른 임포트입니다.


11-12: 기존 메서드 호출 사용처 없음 확인 및 변경 승인

  • findByEmail(, existsByEmail( 호출이 코드베이스 전체에서 더 이상 발견되지 않았습니다.
  • 이메일 + 로그인 타입 조합을 반영한 메서드 시그니처 변경이 복합 고유 제약 조건 요구사항을 충족하며, Spring Data JPA 네이밍 규칙에도 부합합니다.

위 확인을 바탕으로 해당 변경을 승인합니다.

@seung-in-Yoo seung-in-Yoo linked an issue Jul 17, 2025 that may be closed by this pull request
8 tasks
Copy link
Member

@KiSeungMin KiSeungMin left a comment

Choose a reason for hiding this comment

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

수고 많으셨습니다!!!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d63bd83 and 6adb750.

📒 Files selected for processing (4)
  • src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthentication.java (1 hunks)
  • src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java (1 hunks)
  • src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java (2 hunks)
  • src/main/java/com/wayble/server/user/service/auth/AuthService.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/com/wayble/server/user/service/auth/AuthService.java
  • src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java
🔇 Additional comments (3)
src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthentication.java (1)

8-18: 이메일 기반에서 사용자 ID 기반 인증으로의 깔끔한 전환입니다.

주체 식별자를 String email에서 Long userId로 변경한 것이 일관성 있고 올바르게 구현되었습니다. 생성자와 getPrincipal() 메서드가 모두 적절히 업데이트되었습니다.

src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java (2)

16-23: 서명 키 캐싱으로 성능이 개선되었습니다.

서명 키를 지연 초기화하고 캐싱하는 것은 좋은 성능 최적화입니다. 매번 키를 재생성하는 오버헤드를 방지합니다.


25-33: 토큰 생성 로직이 userId 기반으로 올바르게 변경되었습니다.

generateToken 메서드가 이메일 대신 사용자 ID를 받도록 변경되었고, 토큰 주체가 적절히 String.valueOf(userId)로 설정되었습니다.

@seung-in-Yoo seung-in-Yoo merged commit a443d39 into develop Jul 17, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🛠️ fix 기능 오류 및 코드 개선이 필요한 곳 수정 🔧 refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] JWT 기반 로그인 및 회원가입 구현

3 participants