-
Notifications
You must be signed in to change notification settings - Fork 3
Feature : user테이블에서 GitHub 정보 분리, reposiotory 정보 조회 및 저장 #110
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
Conversation
깃허브로 가입하는 순간 바로 깃헙 블로그링크, 아이디, accesstoken가 넘어옴
Walkthrough이 변경 사항은 GitHub 관련 사용자 정보와 저장소 관리를 위한 신규 엔터티, 서비스, 컨트롤러, DTO, 레포지토리 등을 도입합니다. 기존 User 엔터티의 GitHub 액세스 토큰 필드를 분리하여 UserGithubInfo 엔터티로 이동하고, GitHub 저장소 목록 조회 및 저장소 선택 기능을 위한 REST API와 서비스 계층을 추가하였습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant UserGithubController
participant UserGithubService
participant UserGithubInfoRepository
participant WebClient(GitHub API)
Client->>UserGithubController: GET /api/users/github
UserGithubController->>UserGithubService: getGithubRepos(authUser)
UserGithubService->>UserGithubInfoRepository: getUserGithubInfo(userId)
UserGithubService->>WebClient(GitHub API): GET /user/repos (with decrypted token)
WebClient(GitHub API)-->>UserGithubService: List of repos
UserGithubService-->>UserGithubController: List<UserGithubRepoResponse>
UserGithubController-->>Client: 200 OK + repo list
Client->>UserGithubController: POST /api/users/github {repositoryName}
UserGithubController->>UserGithubService: selectGithubRepo(authUser, request)
UserGithubService->>UserGithubInfoRepository: getUserGithubInfo(userId)
UserGithubService->>WebClient(GitHub API): GET /user/repos
WebClient(GitHub API)-->>UserGithubService: List of repos
UserGithubService->>UserGithubInfoRepository: updateGithubInfo
UserGithubService-->>UserGithubController: UserGithubRepoResponse
UserGithubController-->>Client: 200 OK + selected repo
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (13)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserRepositoryImpl.java (2)
7-8: 불필요한 import 제거 필요
UserGithubInfo를 사용하지 않으므로 import 문이 컴파일 경고를 유발할 수 있습니다.-import org.ezcode.codetest.domain.user.model.entity.UserGithubInfo;
56-57: 의미 없는 공백 라인 제거56~57 라인의 빈 줄은 불필요해 보입니다. 코드 일관성을 위해 삭제를 권장합니다.
src/main/java/org/ezcode/codetest/domain/user/model/entity/UserFactory.java (1)
15-22: 프로바이더 문자열 하드코딩 대신 상수/Enum 사용 고려
"github"문자열이 여러 곳에서 반복될 경우 오타로 인한 버그 리스크가 있습니다. Enum 또는 상수로 추출하면 컴파일 타임 체크가 가능해집니다.예시:
public enum OAuthProvider { GITHUB, GOOGLE /* ... */ } // switch (provider.toLowerCase()) → switch (OAuthProvider.valueOf(provider.toUpperCase()))src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/GoogleOAuth2Response.java (1)
51-54: 빈 문자열 반환이 의도한 값인지 확인 필요
getOwner()가 항상""를 반환하면 이후 로직에서 빈 문자열과null을 동일시하지 않을 경우 예외적인 동작이 생길 수 있습니다. 불필요한 분기 로직을 막기 위해null또는Optional사용을 검토해 주세요.- return ""; + return null; // 또는 Optional.ofNullable(...)src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/GithubOAuth2Response.java (1)
3-3: 사용되지 않는 import를 제거하세요.
java.util.Listimport가 코드에서 사용되지 않습니다.-import java.util.List;src/main/java/org/ezcode/codetest/domain/user/repository/UserGithubInfoRepository.java (2)
8-8: 메서드 명세를 더 명확하게 작성해주세요.
getUserGithubInfo(Long id)메서드에서id파라미터가UserGithubInfo의 ID인지User의 ID인지 명확하지 않습니다. 메서드명을getUserGithubInfoByUserId또는getUserGithubInfoById로 변경하거나, JavaDoc을 추가해주세요.
10-12: 메서드 역할의 중복을 검토해주세요.
updateGithubAccessToken과updateGithubInfo메서드가 모두 같은 엔티티를 업데이트하는 것 같습니다. 기능적 차이가 있다면 메서드명을 더 구체적으로 하거나, 하나로 통합하는 것을 고려해보세요.- void updateGithubAccessToken(UserGithubInfo userGithubInfo); - - void updateGithubInfo(UserGithubInfo userGithub); + void updateUserGithubInfo(UserGithubInfo userGithubInfo);src/main/java/org/ezcode/codetest/common/security/hander/CustomSuccessHandler.java (1)
37-54: 생성자 파라미터 순서를 일관성 있게 유지해주세요.생성자에서
UserGithubService파라미터가 중간에 위치해 있습니다. 의존성 주입 순서를 필드 선언 순서와 맞춰서 가독성을 높여주세요.src/main/java/org/ezcode/codetest/domain/user/model/entity/UserGithubInfo.java (3)
19-19: JPA 엔티티 보안을 위해 생성자 접근 제한을 추가해주세요.JPA 엔티티의 기본 생성자는 보통
AccessLevel.PROTECTED로 제한하는 것이 좋습니다.-@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED)
30-31: 필수 필드에 대한 검증을 추가해주세요.
owner필드가nullable = false로 설정되어 있지만, 추가적인 검증 어노테이션이 없습니다. 비즈니스 로직에서 중요한 필드라면@NotBlank등의 검증을 고려해보세요.
49-52: 메서드명을 일관성 있게 작성해주세요.
setGithubRepo메서드는 실제로 repository와 branch 정보를 모두 설정합니다. 메서드명을setRepositoryInfo또는updateRepositoryInfo로 변경하는 것이 더 명확할 것 같습니다.src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoRepositoryImpl.java (1)
15-32: 레포지토리 메서드 중복 제거 검토 필요
updateGithubAccessToken과updateGithubInfo메서드가 모두 동일한save()작업을 수행하고 있습니다.다음과 같이 단일 메서드로 통합을 고려해보세요:
- @Override - public void updateGithubAccessToken(UserGithubInfo userGithubInfo) { - userGithubInfoJpaRepository.save(userGithubInfo); - } - - @Override - public void updateGithubInfo(UserGithubInfo userGithub) { - userGithubInfoJpaRepository.save(userGithubInfo); - } + @Override + public void updateUserGithubInfo(UserGithubInfo userGithubInfo) { + userGithubInfoJpaRepository.save(userGithubInfo); + }다만 현재 구현도 서비스 계층에서 의도를 명확히 표현할 수 있어 유지해도 무방합니다.
src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java (1)
31-41: CRUD 메서드 구현 승인레포지토리 위임 방식의 구현이 적절합니다.
일관성을 위해
@Transactional어노테이션 추가를 고려해보세요:+ @Transactional public void updateUserGithubAccessToken(UserGithubInfo userGithubInfo) { + @Transactional public void createUserGithubInfo(UserGithubInfo userGithubInfo) {단일 레포지토리 호출이므로 필수는 아니지만, 서비스 계층의 일관성을 위해 권장합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (20)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/request/UserGithubRepoSelectRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/GithubOAuth2Response.java(2 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/GoogleOAuth2Response.java(1 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/OAuth2Response.java(1 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserGithubRepoResponse.java(1 hunks)src/main/java/org/ezcode/codetest/common/security/config/WebClientConfig.java(1 hunks)src/main/java/org/ezcode/codetest/common/security/hander/CustomSuccessHandler.java(3 hunks)src/main/java/org/ezcode/codetest/domain/user/exception/code/UserExceptionCode.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java(5 hunks)src/main/java/org/ezcode/codetest/domain/user/model/entity/UserFactory.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/model/entity/UserGithubInfo.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/repository/UserGithubInfoRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/repository/UserRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java(4 hunks)src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java(3 hunks)src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoJpaRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoRepositoryImpl.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserRepositoryImpl.java(2 hunks)src/main/java/org/ezcode/codetest/presentation/usermanagement/UserGithubController.java(1 hunks)
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: minjee2758
PR: ezcode-my/backend#43
File: src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java:77-89
Timestamp: 2025-06-10T02:13:33.890Z
Learning: 이 프로젝트에서는 입력 검증을 DTO 레벨에서 수행하고 있으며, User 엔티티의 팩토리 메서드에서는 별도의 입력 검증을 하지 않는다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능 구현을 위해서는 `repo` scope가 필요하며, 이는 저장소에 대한 읽기/쓰기 권한을 제공한다. `user` scope는 커밋 작성자 정보 설정을 위해 필요하다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능을 구현하려면 `repo` scope가 필수적이며, 이는 public/private 저장소 모두에 대한 전체 접근 권한을 제공한다. 공개 저장소만 대상으로 한다면 `public_repo` scope 사용 가능하다. 더 세밀한 권한 제어가 필요하다면 OAuth App 대신 GitHub App 사용을 권장한다.
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/domain/game/repository/EncounterRepository.java:0-0
Timestamp: 2025-06-15T04:36:57.084Z
Learning: 사용자 chat26666은 개발 중인 기능의 경우 향후 개발 예정인 빈 인터페이스를 의도적으로 남겨두는 것을 선호함. EncounterRepository 인터페이스는 현재 미정의 상태이지만 추후 개발 예정으로 의도적으로 빈 상태로 유지됨.
Learnt from: NCookies
PR: ezcode-my/backend#17
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/ProblemAdminController.java:25-25
Timestamp: 2025-06-02T06:57:37.929Z
Learning: 이 프로젝트에서는 아직 Spring Security가 적용되지 않아서 @PreAuthorize 어노테이션이 주석 처리되어 있음. Spring Security 도입 전까지는 권한 검증 어노테이션들이 비활성화 상태임.
src/main/java/org/ezcode/codetest/domain/user/repository/UserRepository.java (2)
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/domain/game/repository/EncounterRepository.java:0-0
Timestamp: 2025-06-15T04:36:57.084Z
Learning: 사용자 chat26666은 개발 중인 기능의 경우 향후 개발 예정인 빈 인터페이스를 의도적으로 남겨두는 것을 선호함. EncounterRepository 인터페이스는 현재 미정의 상태이지만 추후 개발 예정으로 의도적으로 빈 상태로 유지됨.
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserRepositoryImpl.java (1)
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
src/main/java/org/ezcode/codetest/domain/user/exception/code/UserExceptionCode.java (1)
Learnt from: thezz9
PR: ezcode-my/backend#98
File: src/main/java/org/ezcode/codetest/application/submission/dto/event/SubmissionErrorEvent.java:17-22
Timestamp: 2025-06-25T01:24:30.754Z
Learning: JudgeClient에서 모든 예외를 SubmissionException으로 래핑해서 넘길 계획이므로, SubmissionErrorEvent.resolveCode() 메서드의 캐스팅은 안전할 예정임.
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/request/UserGithubRepoSelectRequest.java (1)
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능 구현을 위해서는 `repo` scope가 필요하며, 이는 저장소에 대한 읽기/쓰기 권한을 제공한다. `user` scope는 커밋 작성자 정보 설정을 위해 필요하다.
src/main/java/org/ezcode/codetest/domain/user/repository/UserGithubInfoRepository.java (1)
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserGithubRepoResponse.java (2)
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능 구현을 위해서는 `repo` scope가 필요하며, 이는 저장소에 대한 읽기/쓰기 권한을 제공한다. `user` scope는 커밋 작성자 정보 설정을 위해 필요하다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능을 구현하려면 `repo` scope가 필수적이며, 이는 public/private 저장소 모두에 대한 전체 접근 권한을 제공한다. 공개 저장소만 대상으로 한다면 `public_repo` scope 사용 가능하다. 더 세밀한 권한 제어가 필요하다면 OAuth App 대신 GitHub App 사용을 권장한다.
src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java (1)
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoJpaRepository.java (1)
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoRepositoryImpl.java (1)
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java (2)
Learnt from: NCookies
PR: ezcode-my/backend#17
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/ProblemAdminController.java:25-25
Timestamp: 2025-06-02T06:57:37.929Z
Learning: 이 프로젝트에서는 아직 Spring Security가 적용되지 않아서 @PreAuthorize 어노테이션이 주석 처리되어 있음. Spring Security 도입 전까지는 권한 검증 어노테이션들이 비활성화 상태임.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능을 구현하려면 `repo` scope가 필수적이며, 이는 public/private 저장소 모두에 대한 전체 접근 권한을 제공한다. 공개 저장소만 대상으로 한다면 `public_repo` scope 사용 가능하다. 더 세밀한 권한 제어가 필요하다면 OAuth App 대신 GitHub App 사용을 권장한다.
src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java (2)
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능 구현을 위해서는 `repo` scope가 필요하며, 이는 저장소에 대한 읽기/쓰기 권한을 제공한다. `user` scope는 커밋 작성자 정보 설정을 위해 필요하다.
Learnt from: NCookies
PR: ezcode-my/backend#17
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/ProblemAdminController.java:25-25
Timestamp: 2025-06-02T06:57:37.929Z
Learning: 이 프로젝트에서는 아직 Spring Security가 적용되지 않아서 @PreAuthorize 어노테이션이 주석 처리되어 있음. Spring Security 도입 전까지는 권한 검증 어노테이션들이 비활성화 상태임.
src/main/java/org/ezcode/codetest/presentation/usermanagement/UserGithubController.java (3)
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능 구현을 위해서는 `repo` scope가 필요하며, 이는 저장소에 대한 읽기/쓰기 권한을 제공한다. `user` scope는 커밋 작성자 정보 설정을 위해 필요하다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능을 구현하려면 `repo` scope가 필수적이며, 이는 public/private 저장소 모두에 대한 전체 접근 권한을 제공한다. 공개 저장소만 대상으로 한다면 `public_repo` scope 사용 가능하다. 더 세밀한 권한 제어가 필요하다면 OAuth App 대신 GitHub App 사용을 권장한다.
Learnt from: NCookies
PR: ezcode-my/backend#17
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/ProblemAdminController.java:25-25
Timestamp: 2025-06-02T06:57:37.929Z
Learning: 이 프로젝트에서는 아직 Spring Security가 적용되지 않아서 @PreAuthorize 어노테이션이 주석 처리되어 있음. Spring Security 도입 전까지는 권한 검증 어노테이션들이 비활성화 상태임.
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (1)
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
🧬 Code Graph Analysis (6)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/GithubOAuth2Response.java (1)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/GoogleOAuth2Response.java (1)
Schema(7-56)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/request/UserGithubRepoSelectRequest.java (1)
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/GithubOAuth2Response.java (1)
Schema(8-61)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoJpaRepository.java (1)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoRepositoryImpl.java (1)
Repository(9-33)
src/main/java/org/ezcode/codetest/domain/user/model/entity/UserGithubInfo.java (2)
src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java (1)
Entity(25-192)src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserGithubRepoResponse.java (1)
Getter(7-17)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoRepositoryImpl.java (1)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserRepositoryImpl.java (1)
Repository(13-58)
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (1)
src/main/java/org/ezcode/codetest/domain/user/model/entity/UserFactory.java (1)
UserFactory(7-31)
🔇 Additional comments (13)
src/main/java/org/ezcode/codetest/domain/user/repository/UserRepository.java (1)
23-24: ```shell
#!/bin/bash
echo "==== UserGithubService.java ===="
rg -n -C3 "updateUserGithubAccessToken" src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java
echo "==== UserRepositoryImpl.java ===="
rg -n -C3 "updateUserGithubAccessToken" src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserRepositoryImpl.java</details> <details> <summary>src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/OAuth2Response.java (1)</summary> `23-24`: **새 메서드 추가 확인 완료** `getOwner()` 추가로 GitHub 전용 정보가 명확히 구분되었습니다. 인터페이스 확장은 문제 없어 보입니다. </details> <details> <summary>src/main/java/org/ezcode/codetest/domain/user/exception/code/UserExceptionCode.java (1)</summary> `14-15`: **새로운 GitHub 정보 관련 예외 코드 추가가 적절합니다.** GitHub 기능 구현에 필요한 예외 처리를 위한 코드가 올바르게 추가되었습니다. 기존 enum 패턴을 잘 따르고 있고 메시지도 명확합니다. </details> <details> <summary>src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/GithubOAuth2Response.java (1)</summary> `56-60`: **getOwner() 메서드 구현이 올바릅니다.** GitHub의 login 속성을 올바르게 반환하고 있으며, 스키마 어노테이션도 적절합니다. OAuth2Response 인터페이스의 새로운 메서드를 잘 구현했습니다. </details> <details> <summary>src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java (1)</summary> `35-35`: **추가된 UserGithubInfoRepository 필드의 사용 여부를 확인하세요.** UserGithubInfoRepository 필드가 추가되었지만 이 서비스 클래스에서 실제로 사용되지 않는 것으로 보입니다. GitHub 관련 기능이 UserGithubService로 분리되었다면 이 필드가 필요한지 검토해보세요. 다음 스크립트로 이 필드의 사용 여부를 확인해보겠습니다: ```shell #!/bin/bash # UserDomainService에서 userGithubInfoRepository 필드 사용 여부 확인 rg -A 5 -B 5 "userGithubInfoRepository" --type javasrc/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserGithubInfoJpaRepository.java (1)
8-13: JPA 리포지토리 인터페이스가 올바르게 구현되었습니다.Spring Data JPA 규칙을 잘 따르고 있으며, 메서드 명명 규칙도 적절합니다. User 엔터티와 User ID로 UserGithubInfo를 조회하는 두 메서드 모두 필요한 기능을 제공합니다.
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/request/UserGithubRepoSelectRequest.java (1)
5-9: 요청 DTO 레코드가 적절하게 구현되었습니다.record 문법을 올바르게 사용했고, Swagger 어노테이션도 적절히 설정되어 있습니다. GitHub 리포지토리 선택 기능에 필요한 간단하고 명확한 구조입니다.
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserGithubRepoResponse.java (1)
1-17: 구현이 잘 되어 있습니다.DTO 구조가 명확하고 Swagger 문서화도 적절합니다. GitHub 저장소 정보를 전달하는 용도로 적합합니다.
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (1)
107-107: OAuth2Response 인터페이스의 메서드 호환성을 확인해주세요.
response.getOwner()메서드가 모든 OAuth2Response 구현체에서 지원되는지 확인이 필요합니다. GitHub 전용 메서드라면 타입 캐스팅이나 다른 방법을 고려해보세요.다음 스크립트로 OAuth2Response 인터페이스와 구현체들을 확인해보겠습니다:
#!/bin/bash # OAuth2Response 인터페이스와 구현체에서 getOwner 메서드 지원 여부 확인 echo "OAuth2Response 인터페이스 확인:" ast-grep --pattern 'interface OAuth2Response { $$$ }' echo "OAuth2Response 구현체들 확인:" ast-grep --pattern 'class $_ implements OAuth2Response { $$$ }' echo "getOwner 메서드 사용 확인:" rg -A 3 -B 3 "getOwner"src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java (4)
75-75: GitHub 자동 푸시 상태 관리 필드 추가 승인
gitPushStatus필드 추가는 GitHub 통합 기능의 활성화 상태를 관리하는 명확한 용도로 적절합니다.
94-94: 이메일 사용자의 기본 GitHub 푸시 상태 설정 승인이메일 가입 사용자의
gitPushStatus를 기본값false로 설정하여 명시적인 활성화가 필요하도록 한 것이 보안상 적절합니다.
112-112: 소셜/GitHub 사용자의 기본 푸시 상태 설정 승인모든 사용자 유형에서
gitPushStatus를 일관되게false로 초기화하여 명시적 활성화를 요구하는 보안 관점이 적절합니다.Also applies to: 128-128
135-135: 생성자 파라미터 추가 및 필드 할당 승인
gitPushStatus파라미터를 생성자에 추가하고 필드에 할당하는 구현이 적절합니다.Also applies to: 146-146
| return WebClient.builder() | ||
| .baseUrl("https://api.github.com") | ||
| .defaultHeader(HttpHeaders.ACCEPT, "application/vnd.github+json") | ||
| .build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
GitHub API 요청을 위해 User-Agent 헤더 추가 및 URL 하드코딩 제거 제안
GitHub API는 User-Agent 헤더가 없는 요청을 거부합니다. 또한 베이스 URL을 소스에 하드코딩하면 테스트/스테이징 환경 분리가 어려워집니다.
다음과 같이 수정하면 재사용성과 환경 분리가 용이합니다.
return WebClient.builder()
- .baseUrl("https://api.github.com")
- .defaultHeader(HttpHeaders.ACCEPT, "application/vnd.github+json")
+ .baseUrl("${github.api.base-url:https://api.github.com}")
+ .defaultHeader(HttpHeaders.ACCEPT, "application/vnd.github+json")
+ .defaultHeader(HttpHeaders.USER_AGENT, "ezcode-codetest-server")
.build();application.yml 예시:
github:
api:
base-url: https://api.github.com🤖 Prompt for AI Agents
In src/main/java/org/ezcode/codetest/common/security/config/WebClientConfig.java
around lines 12 to 15, the WebClient configuration is missing the required
'User-Agent' header for GitHub API requests and has the base URL hardcoded. To
fix this, add a default header for 'User-Agent' with an appropriate value, and
refactor the base URL to be injected from a configuration property (e.g., from
application.yml) instead of hardcoding it, enabling easier environment
separation and reuse.
src/main/java/org/ezcode/codetest/common/security/hander/CustomSuccessHandler.java
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/domain/user/model/entity/UserGithubInfo.java
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java
Outdated
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/presentation/usermanagement/UserGithubController.java
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/presentation/usermanagement/UserGithubController.java
Show resolved
Hide resolved
There was a problem hiding this 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
♻️ Duplicate comments (1)
src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java (1)
69-75: GitHub API 오류 처리가 잘 구현되었습니다.구체적인 GitHub API 오류 메시지를 포함하는 예외 처리가 유용합니다. 다만 예외 타입을 조정하는 것을 권장합니다.
이전 리뷰에서 논의된 대로,
IllegalAccessException대신 더 적절한 예외 타입 사용을 고려해주세요.
🧹 Nitpick comments (2)
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (1)
107-118: GitHub 정보 생성 로직이 적절히 구현되었습니다.UserGithubInfo 엔티티 생성과 예외 처리가 잘 되어 있으나, 더 구체적인 예외 처리를 권장합니다.
다음과 같이 더 구체적인 예외 처리를 고려해보세요:
- try { - userGithubService.createUserGithubInfo(userGithubInfo); - } catch (Exception e) { - throw new UserException(UserExceptionCode.NO_GITHUB_INFO); - } + try { + userGithubService.createUserGithubInfo(userGithubInfo); + } catch (DataAccessException e) { + log.error("Failed to create UserGithubInfo for user: {}", user.getId(), e); + throw new UserException(UserExceptionCode.NO_GITHUB_INFO); + }src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java (1)
95-100: Repository 검증 로직에서 성능 최적화가 필요합니다.매번 GitHub API를 재호출하는 것은 비효율적입니다. 캐시된 데이터 활용을 고려해주세요.
다음과 같은 개선을 권장합니다:
- 성능 최적화: API 재호출 대신 이미 조회된 repos 리스트 활용
- 일관된 예외 처리: 도메인 예외 사용으로 일관성 유지
- List<UserGithubRepoResponse> repos = getGithubRepos(authUser); - - UserGithubRepoResponse selectedRepo = repos.stream() - .filter(repo -> repo.getRepoName().equals(request.repositoryName())) - .findFirst() - .orElseThrow(() -> new UserException(UserExceptionCode.NO_GITHUB_REPO)); + // 이미 호출된 API 결과를 재사용하거나 캐싱 전략 고려 + UserGithubRepoResponse selectedRepo = repos.stream() + .filter(repo -> repo.getRepoName().equals(request.repositoryName())) + .findFirst() + .orElseThrow(() -> new UserException(UserExceptionCode.NO_GITHUB_REPO));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/main/java/org/ezcode/codetest/common/security/config/WebClientConfig.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/exception/code/UserExceptionCode.java(1 hunks)src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java(4 hunks)src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java(1 hunks)src/main/java/org/ezcode/codetest/presentation/usermanagement/UserGithubController.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/main/java/org/ezcode/codetest/common/security/config/WebClientConfig.java
- src/main/java/org/ezcode/codetest/presentation/usermanagement/UserGithubController.java
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: minjee2758
PR: ezcode-my/backend#110
File: src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java:102-112
Timestamp: 2025-06-27T06:03:05.687Z
Learning: `CustomOAuth2UserService`의 `updateGithubUrl` 메서드는 새로운 유저 생성 시나 기존 유저가 새로운 AuthType을 추가할 때만 호출되므로, `UserGithubInfo` 중복 생성 가능성이 없다. 별도의 중복 체크 로직이 불필요하다.
Learnt from: chat26666
PR: ezcode-my/backend#37
File: src/main/java/org/ezcode/codetest/infrastructure/elasticsearch/repository/ProblemElasticsearchRepositoryDsl.java:10-10
Timestamp: 2025-06-06T19:56:27.759Z
Learning: When user chat26666 mentions that code was implemented in a previous PR but explanation was missing, they may submit a follow-up PR just to add documentation/explanation without the actual implementation code.
Learnt from: minjee2758
PR: ezcode-my/backend#43
File: src/main/java/org/ezcode/codetest/domain/user/model/entity/User.java:77-89
Timestamp: 2025-06-10T02:13:33.890Z
Learning: 이 프로젝트에서는 입력 검증을 DTO 레벨에서 수행하고 있으며, User 엔티티의 팩토리 메서드에서는 별도의 입력 검증을 하지 않는다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능 구현을 위해서는 `repo` scope가 필요하며, 이는 저장소에 대한 읽기/쓰기 권한을 제공한다. `user` scope는 커밋 작성자 정보 설정을 위해 필요하다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능을 구현하려면 `repo` scope가 필수적이며, 이는 public/private 저장소 모두에 대한 전체 접근 권한을 제공한다. 공개 저장소만 대상으로 한다면 `public_repo` scope 사용 가능하다. 더 세밀한 권한 제어가 필요하다면 OAuth App 대신 GitHub App 사용을 권장한다.
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/domain/game/repository/EncounterRepository.java:0-0
Timestamp: 2025-06-15T04:36:57.084Z
Learning: 사용자 chat26666은 개발 중인 기능의 경우 향후 개발 예정인 빈 인터페이스를 의도적으로 남겨두는 것을 선호함. EncounterRepository 인터페이스는 현재 미정의 상태이지만 추후 개발 예정으로 의도적으로 빈 상태로 유지됨.
Learnt from: NCookies
PR: ezcode-my/backend#17
File: src/main/java/org/ezcode/codetest/presentation/problemmanagement/ProblemAdminController.java:25-25
Timestamp: 2025-06-02T06:57:37.929Z
Learning: 이 프로젝트에서는 아직 Spring Security가 적용되지 않아서 @PreAuthorize 어노테이션이 주석 처리되어 있음. Spring Security 도입 전까지는 권한 검증 어노테이션들이 비활성화 상태임.
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (3)
Learnt from: minjee2758
PR: ezcode-my/backend#110
File: src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java:102-112
Timestamp: 2025-06-27T06:03:05.687Z
Learning: `CustomOAuth2UserService`의 `updateGithubUrl` 메서드는 새로운 유저 생성 시나 기존 유저가 새로운 AuthType을 추가할 때만 호출되므로, `UserGithubInfo` 중복 생성 가능성이 없다. 별도의 중복 체크 로직이 불필요하다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능 구현을 위해서는 `repo` scope가 필요하며, 이는 저장소에 대한 읽기/쓰기 권한을 제공한다. `user` scope는 커밋 작성자 정보 설정을 위해 필요하다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능을 구현하려면 `repo` scope가 필수적이며, 이는 public/private 저장소 모두에 대한 전체 접근 권한을 제공한다. 공개 저장소만 대상으로 한다면 `public_repo` scope 사용 가능하다. 더 세밀한 권한 제어가 필요하다면 OAuth App 대신 GitHub App 사용을 권장한다.
src/main/java/org/ezcode/codetest/domain/user/exception/code/UserExceptionCode.java (2)
Learnt from: minjee2758
PR: ezcode-my/backend#110
File: src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java:102-112
Timestamp: 2025-06-27T06:03:05.687Z
Learning: `CustomOAuth2UserService`의 `updateGithubUrl` 메서드는 새로운 유저 생성 시나 기존 유저가 새로운 AuthType을 추가할 때만 호출되므로, `UserGithubInfo` 중복 생성 가능성이 없다. 별도의 중복 체크 로직이 불필요하다.
Learnt from: thezz9
PR: ezcode-my/backend#98
File: src/main/java/org/ezcode/codetest/application/submission/dto/event/SubmissionErrorEvent.java:17-22
Timestamp: 2025-06-25T01:24:30.754Z
Learning: JudgeClient에서 모든 예외를 SubmissionException으로 래핑해서 넘길 계획이므로, SubmissionErrorEvent.resolveCode() 메서드의 캐스팅은 안전할 예정임.
src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java (5)
Learnt from: minjee2758
PR: ezcode-my/backend#110
File: src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java:102-112
Timestamp: 2025-06-27T06:03:05.687Z
Learning: `CustomOAuth2UserService`의 `updateGithubUrl` 메서드는 새로운 유저 생성 시나 기존 유저가 새로운 AuthType을 추가할 때만 호출되므로, `UserGithubInfo` 중복 생성 가능성이 없다. 별도의 중복 체크 로직이 불필요하다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능 구현을 위해서는 `repo` scope가 필요하며, 이는 저장소에 대한 읽기/쓰기 권한을 제공한다. `user` scope는 커밋 작성자 정보 설정을 위해 필요하다.
Learnt from: minjee2758
PR: ezcode-my/backend#105
File: src/main/resources/application.properties:127-127
Timestamp: 2025-06-26T09:43:03.896Z
Learning: GitHub OAuth에서 자동 커밋 기능을 구현하려면 `repo` scope가 필수적이며, 이는 public/private 저장소 모두에 대한 전체 접근 권한을 제공한다. 공개 저장소만 대상으로 한다면 `public_repo` scope 사용 가능하다. 더 세밀한 권한 제어가 필요하다면 OAuth App 대신 GitHub App 사용을 권장한다.
Learnt from: thezz9
PR: ezcode-my/backend#73
File: src/main/java/org/ezcode/codetest/infrastructure/openai/OpenAIReviewClient.java:52-64
Timestamp: 2025-06-18T11:42:03.701Z
Learning: OpenAI API 클라이언트에서는 두 가지 재시도 전략을 사용한다: 1) WebClient의 retryWhen은 네트워크/HTTP 에러 및 타임아웃에 대한 재시도, 2) 외부 for 루프는 API 응답 포맷 검증 실패에 대한 재시도. 이는 서로 다른 실패 상황을 처리하는 독립적인 메커니즘이다.
Learnt from: chat26666
PR: ezcode-my/backend#88
File: src/main/java/org/ezcode/codetest/application/game/play/GamePlayUseCase.java:0-0
Timestamp: 2025-06-21T21:29:21.785Z
Learning: JwtUtil.extractClaims() 메서드는 이미 JwtException을 catch하여 ServerException으로 변환하는 예외 처리가 구현되어 있으므로, 호출하는 곳에서 추가적인 try-catch 블록이 필요하지 않습니다.
🔇 Additional comments (4)
src/main/java/org/ezcode/codetest/domain/user/exception/code/UserExceptionCode.java (1)
14-16: 새로운 GitHub 관련 예외 코드가 적절히 추가되었습니다.기존 enum 패턴을 잘 따르고 있으며, 한국어 메시지도 명확합니다. GitHub 기능에 필요한 도메인별 예외 처리가 잘 구성되어 있습니다.
src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.java (1)
8-9: 필요한 의존성과 임포트가 적절히 추가되었습니다.GitHub 기능 지원을 위한 새로운 서비스 의존성과 엔티티 임포트가 잘 구성되어 있습니다.
Also applies to: 14-14, 36-36
src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java (2)
33-43: 기본 CRUD 메서드들이 적절히 구현되었습니다.UserGithubInfo 엔티티에 대한 생성, 조회, 업데이트 메서드가 잘 구성되어 있습니다.
46-47: 트랜잭션 어노테이션 사용이 적절한지 검토해주세요.조회 전용 메서드에
@Transactional이 필요한지 확인해주세요.이 프로젝트의 트랜잭션 관리 패턴을 확인하기 위해 다음 스크립트를 실행하겠습니다:
#!/bin/bash # 프로젝트의 트랜잭션 관리 패턴 확인 echo "=== UseCase 레벨 트랜잭션 패턴 확인 ===" rg -A 3 -B 1 "@Transactional" --type java echo "=== 도메인 서비스의 트랜잭션 사용 패턴 ===" fd "Service\.java$" src/main/java/org/ezcode/codetest/domain -x rg -l "@Transactional" {}learned context에 따르면 이 프로젝트는 UseCase 레벨에서 트랜잭션을 관리한다고 되어 있는데, 현재 도메인 서비스에서 직접 트랜잭션을 사용하는 것이 일관된 패턴인지 확인이 필요합니다.
| .map(repo -> new UserGithubRepoResponse( | ||
| repo.get("name").toString(), | ||
| repo.get("default_branch").toString() | ||
| )) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
API 응답 파싱에서 null 안전성을 강화해주세요.
GitHub API 응답에서 값 추출 시 null 체크가 필요합니다.
다음과 같이 안전한 파싱을 적용해주세요:
.map(repo -> new UserGithubRepoResponse(
- repo.get("name").toString(),
- repo.get("default_branch").toString()
+ Objects.toString(repo.get("name"), ""),
+ Objects.toString(repo.get("default_branch"), "main")
))추가로 Objects 임포트가 필요합니다:
import java.util.Objects;🤖 Prompt for AI Agents
In src/main/java/org/ezcode/codetest/domain/user/service/UserGithubService.java
around lines 79 to 82, the code extracts values from the GitHub API response
without null checks, which can cause NullPointerExceptions. Update the mapping
to safely handle potential null values by using Objects.toString() with a
default empty string or similar null-safe methods for both "name" and
"default_branch" fields. Also, add the import statement for java.util.Objects at
the top of the file.
작업 내용
변경 사항
UserGithubInfo 엔티티
UserGithubInfoRepository / UserGithubInfoJpaRepository
UserGithubRepoResponse DTO
UserGithubRepoSelectRequest DTO
WebClientConfig
UserGithubService
UserGithubController
참고 사항
코드 리뷰 전 확인 체크리스트
type :)Summary by CodeRabbit
신규 기능
버그 수정
문서화
기타