[FEAT] 연동할 레포지토리 목록 조회 API 구현#34
Conversation
|
Warning Review limit reached
More reviews will be available in 44 minutes and 45 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughCI/CD 워크플로우를 프로필 기반 설정으로 마이그레이션하고, GitHub API를 통해 인증된 사용자의 계정/저장소/브랜치 목록을 조회하는 새로운 REST API를 구현한다. 외부 API 통합, 입력 검증, 비즈니스 로직 및 HTTP 엔드포인트를 단계적으로 구성한다. ChangesGitHub 저장소 조회 API 기능
Sequence DiagramsequenceDiagram
participant Client as 클라이언트
participant Controller as AnalysisRequestController
participant Service as AnalysisRequestService
participant Validator as AnalysisRequestValidator
participant GithubClient as GithubRepositoryClient
participant GitHub as GitHub API
Client->>Controller: GET /analysis/request/accounts
Controller->>Service: getLinkableGithubAccounts(userId)
Service->>Validator: validateLoginUser(userId)
Validator-->>Service: User
Service->>Validator: validateGithubToken(token)
Validator-->>Service: token
Service->>GithubClient: getUserAccount(token)
GithubClient->>GitHub: GET /user
GitHub-->>GithubClient: GithubUserAccountResponse
GithubClient-->>Service: GithubUserAccountResponse
Service->>GithubClient: getUserOrganizations(token)
GithubClient->>GitHub: GET /user/orgs
GitHub-->>GithubClient: List<GithubAccountResponse>
GithubClient-->>Service: List<GithubAccountResponse>
Service-->>Controller: LinkableGithubAccountListResponse
Controller-->>Client: ApiResponse<LinkableGithubAccountListResponse>
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsStopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (5)
.github/workflows/cd.yml (1)
72-76: ⚡ Quick win배포 이미지는
latest대신 커밋 SHA로 고정하세요.Line [75]에서
latest를 사용하면 재시도/동시 실행 시 의도와 다른 이미지가 올라갈 수 있습니다. Line [56]에서 이미 SHA 태그를 푸시하므로 배포도 동일 태그를 쓰는 편이 안전합니다.제안 diff
- name: Deploy to server with Docker uses: appleboy/ssh-action@master env: DOCKER_REPO: ${{ secrets.DOCKER_REPO }} + IMAGE_TAG: ${{ github.sha }} with: @@ - envs: DOCKER_REPO + envs: DOCKER_REPO,IMAGE_TAG script: | @@ - image: ${DOCKER_REPO}:latest + image: ${DOCKER_REPO}:${IMAGE_TAG}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/cd.yml around lines 72 - 76, Replace the hardcoded ":latest" in the docker-compose heredoc with the same SHA tag variable used when pushing the image earlier so the deployed image matches the pushed image; specifically update the generated docker-compose block where image: ${DOCKER_REPO}:latest is written to use the commit SHA variable (the same variable used at the push step) instead of "latest" so docker-compose pulls ${DOCKER_REPO}:${SHA_TAG_VAR} and not ${DOCKER_REPO}:latest.src/main/java/SeCause/SeCause_be/domain/analysis/code/AnalysisErrorCode.java (1)
13-16: 💤 Low value선택적 개선: 에러 코드 접미사 패턴에 대한 설명 추가를 고려하세요.
GITHUB_TOKEN_INVALID은"ANALYSIS_GITHUB4012"(401 + 접미사 2)를,GITHUB_ACCOUNT_NOT_FOUND는"ANALYSIS_GITHUB4041"(404 + 접미사 1)을 사용하는 반면, 다른 코드들은 접미사가 없습니다.UserErrorCode에USER_GITHUB4011이 있는 것으로 보아 도메인 간 충돌 방지를 위한 의도적 설계로 보이지만, 이러한 패턴이 문서화되어 있지 않으면 향후 유지보수 시 혼란을 줄 수 있습니다.접미사 규칙을 enum 상단에 주석으로 추가하거나, 불필요한 경우 정규화를 고려해보세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/SeCause/SeCause_be/domain/analysis/code/AnalysisErrorCode.java` around lines 13 - 16, The enum values in AnalysisErrorCode (e.g., GITHUB_TOKEN_INVALID, GITHUB_ACCOUNT_NOT_FOUND) use numeric-suffix variants like "ANALYSIS_GITHUB4012"/"ANALYSIS_GITHUB4041" while other codes lack suffixes; either document this suffix convention or normalize the codes. Update the AnalysisErrorCode enum declaration to include a short Javadoc/comment at the top describing the suffix pattern (e.g., suffix meaning and cross-domain collision avoidance with UserErrorCode such as USER_GITHUB4011), or rename/standardize the constants so all GitHub-related codes follow a consistent format across AnalysisErrorCode and UserErrorCode. Ensure the comment references the exact pattern and examples (ANALYSIS_GITHUB4012, ANALYSIS_GITHUB4041) so future maintainers understand the rule.src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryListResponse.java (1)
9-10: ⚡ Quick win리스트 래퍼 DTO도
List.copyOf로 고정하는 편이 안전합니다.입력 리스트를 그대로 보관하면 생성 이후 외부 변경에 노출됩니다.
제안 패치
public static LinkableRepositoryListResponse from(List<LinkableRepositoryResponse> repositories) { - return new LinkableRepositoryListResponse(repositories); + return new LinkableRepositoryListResponse(List.copyOf(repositories)); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryListResponse.java` around lines 9 - 10, The from factory method in LinkableRepositoryListResponse currently stores the incoming List<LinkableRepositoryResponse> directly which allows external mutation after construction; change it to create an unmodifiable copy (e.g. via List.copyOf) when assigning to the internal field so the constructor or the from method (LinkableRepositoryListResponse.from) stores List.copyOf(repositories) (or have the constructor call List.copyOf on its parameter) to ensure immutability.src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableGithubAccountListResponse.java (1)
9-10: ⚡ Quick win응답 DTO에 전달된 리스트를 방어적으로 복사하세요.
현재
from(...)가 입력 리스트 참조를 그대로 보관해서, 호출 측 변경이 응답 객체에 반영될 수 있습니다.제안 패치
public static LinkableGithubAccountListResponse from(List<LinkableGithubAccountResponse> accounts) { - return new LinkableGithubAccountListResponse(accounts); + return new LinkableGithubAccountListResponse(List.copyOf(accounts)); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableGithubAccountListResponse.java` around lines 9 - 10, from(List<LinkableGithubAccountResponse> accounts) currently stores the incoming list reference directly; make a defensive copy so external mutations don't affect the DTO by creating a new ArrayList copy (e.g., new ArrayList<>(accounts)) when constructing LinkableGithubAccountListResponse or inside its constructor; update the constructor or the static factory method in class LinkableGithubAccountListResponse to assign an unmodifiable/ copied list (use Collections.unmodifiableList if immutability is desired) instead of keeping the original reference.src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryBranchListResponse.java (1)
9-10: ⚡ Quick win브랜치 목록 응답도 외부 변경 차단이 필요합니다.
from(...)에서 전달 리스트를 복사하지 않으면 응답 불변성이 깨질 수 있습니다.제안 패치
public static LinkableRepositoryBranchListResponse from(List<LinkableRepositoryBranchResponse> branches) { - return new LinkableRepositoryBranchListResponse(branches); + return new LinkableRepositoryBranchListResponse(List.copyOf(branches)); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryBranchListResponse.java` around lines 9 - 10, The static factory method LinkableRepositoryBranchListResponse.from(List<LinkableRepositoryBranchResponse> branches) currently stores the caller-supplied list directly which breaks response immutability; update from(...) (and the LinkableRepositoryBranchListResponse constructor if needed) to defensively copy the incoming list (e.g. new ArrayList<>(branches)) and expose or store an unmodifiable view (Collections.unmodifiableList(...)) so external mutations cannot affect the response state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/main/java/SeCause/SeCause_be/domain/analysis/client/GithubRepositoryClient.java`:
- Around line 31-53: The getUserAccount method in GithubRepositoryClient uses
webClient.block() without a timeout; update it to enforce a request timeout
(e.g., call block with a Duration like block(Duration.ofSeconds(10))) or
configure the webClient instance with a global response timeout (build WebClient
with a ReactorClientHttpConnector using
HttpClient.create().responseTimeout(Duration.ofSeconds(10))). Modify either the
getUserAccount call or the webClient construction so that webClient calls time
out instead of blocking indefinitely, and keep the existing exception handling
(Unauthorized/Forbidden/RequestFailed) intact.
- Around line 113-137: getList in GithubRepositoryClient currently calls
webClient.block() without a timeout and doesn't handle GitHub pagination (only
per_page=100), risking hangs and truncated results; update getList to apply a
request timeout (either use block(Duration) or configure a connector/read/write
timeout on WebClient in WebClientConfig) and implement pagination by iterating
pages: perform requests (use exchangeToMono/flatMap to access response headers)
to read the Link header or include a page parameter (e.g., page query) in the
uriFunction and loop until no rel="next", aggregating results into a single
List<T> before returning; ensure error handling for timeouts maps to the
existing AnalysisException codes and reuse webClient and getList signatures (or
add an internal helper) so callers are unchanged.
In
`@src/main/java/SeCause/SeCause_be/domain/analysis/service/AnalysisRequestService.java`:
- Around line 63-69: 현재 validatedAccountName과 userAccount.login()을 대소문자 구분 없이
비교하지 않아 케이스가 다른 동일 계정명에 대해 개인 저장소 조회 대신 조직 검증 경로로 들어가는 문제가 있습니다;
validatedAccountName.equals(userAccount.login()) 비교를
validatedAccountName.equalsIgnoreCase(userAccount.login())로 바꾸거나 두 값을
toLowerCase()/toUpperCase로 정규화한 뒤 비교하도록 수정하고(참조: validatedAccountName,
userAccount.login(), githubRepositoryClient.getUserOwnedRepositories,
analysisRequestValidator.validateOrganizationAccount,
githubRepositoryClient.getUserOrganizations) 개인 계정 분기에서 항상 올바른 개인 저장소
조회(githubRepositoryClient.getUserOwnedRepositories)가 호출되도록 보장하세요.
In
`@src/main/java/SeCause/SeCause_be/domain/analysis/validator/AnalysisRequestValidator.java`:
- Around line 35-40: validateGithubAccountName currently returns the raw
accountName which allows equivalent names with whitespace/case differences to be
rejected later; normalize the input by trimming whitespace and applying a
consistent case (e.g., toLowerCase()) inside validateGithubAccountName before
validation and return, and ensure the same normalization is applied wherever the
code compares GitHub account strings (the comparison logic referenced near lines
47-49) so comparisons use the normalized form.
In `@src/main/resources/application-dev.yml`:
- Around line 35-36: application-dev.yml uses environment variable keys
refresh-secret and refresh-token-hash-secret mapped to ${REFRESH_SECRET} and
${REFRESH_TOKEN_HASH_SECRET}, which are inconsistent with other profiles; update
these placeholders to use the JWT-prefixed env vars (replace ${REFRESH_SECRET}
with ${JWT_REFRESH_SECRET} and ${REFRESH_TOKEN_HASH_SECRET} with
${JWT_REFRESH_HASH_SECRET}) so the keys (refresh-secret,
refresh-token-hash-secret) read from the same JWT_* environment variables used
by other profiles.
In `@src/main/resources/application.yml`:
- Around line 1-3: Remove the hard-coded spring.profiles.active: local default
from application.yml so the app doesn't fall back to the local profile when
SPRING_PROFILES_ACTIVE is absent; specifically, delete or unset the
spring.profiles.active entry (the "spring.profiles.active" key and its "local"
value) and rely on environment/property injection (SPRING_PROFILES_ACTIVE or
--spring.profiles.active) at runtime, or replace it with a non-binding
placeholder (e.g., leave it out or set to null) and document that profiles must
be provided when starting the app.
---
Nitpick comments:
In @.github/workflows/cd.yml:
- Around line 72-76: Replace the hardcoded ":latest" in the docker-compose
heredoc with the same SHA tag variable used when pushing the image earlier so
the deployed image matches the pushed image; specifically update the generated
docker-compose block where image: ${DOCKER_REPO}:latest is written to use the
commit SHA variable (the same variable used at the push step) instead of
"latest" so docker-compose pulls ${DOCKER_REPO}:${SHA_TAG_VAR} and not
${DOCKER_REPO}:latest.
In
`@src/main/java/SeCause/SeCause_be/domain/analysis/code/AnalysisErrorCode.java`:
- Around line 13-16: The enum values in AnalysisErrorCode (e.g.,
GITHUB_TOKEN_INVALID, GITHUB_ACCOUNT_NOT_FOUND) use numeric-suffix variants like
"ANALYSIS_GITHUB4012"/"ANALYSIS_GITHUB4041" while other codes lack suffixes;
either document this suffix convention or normalize the codes. Update the
AnalysisErrorCode enum declaration to include a short Javadoc/comment at the top
describing the suffix pattern (e.g., suffix meaning and cross-domain collision
avoidance with UserErrorCode such as USER_GITHUB4011), or rename/standardize the
constants so all GitHub-related codes follow a consistent format across
AnalysisErrorCode and UserErrorCode. Ensure the comment references the exact
pattern and examples (ANALYSIS_GITHUB4012, ANALYSIS_GITHUB4041) so future
maintainers understand the rule.
In
`@src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableGithubAccountListResponse.java`:
- Around line 9-10: from(List<LinkableGithubAccountResponse> accounts) currently
stores the incoming list reference directly; make a defensive copy so external
mutations don't affect the DTO by creating a new ArrayList copy (e.g., new
ArrayList<>(accounts)) when constructing LinkableGithubAccountListResponse or
inside its constructor; update the constructor or the static factory method in
class LinkableGithubAccountListResponse to assign an unmodifiable/ copied list
(use Collections.unmodifiableList if immutability is desired) instead of keeping
the original reference.
In
`@src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryBranchListResponse.java`:
- Around line 9-10: The static factory method
LinkableRepositoryBranchListResponse.from(List<LinkableRepositoryBranchResponse>
branches) currently stores the caller-supplied list directly which breaks
response immutability; update from(...) (and the
LinkableRepositoryBranchListResponse constructor if needed) to defensively copy
the incoming list (e.g. new ArrayList<>(branches)) and expose or store an
unmodifiable view (Collections.unmodifiableList(...)) so external mutations
cannot affect the response state.
In
`@src/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryListResponse.java`:
- Around line 9-10: The from factory method in LinkableRepositoryListResponse
currently stores the incoming List<LinkableRepositoryResponse> directly which
allows external mutation after construction; change it to create an unmodifiable
copy (e.g. via List.copyOf) when assigning to the internal field so the
constructor or the from method (LinkableRepositoryListResponse.from) stores
List.copyOf(repositories) (or have the constructor call List.copyOf on its
parameter) to ensure immutability.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 858aa8ee-bbc1-4f23-85ff-67ea9c09d4b4
📒 Files selected for processing (26)
.github/workflows/cd.yml.github/workflows/ci.yml.gitignoresrc/main/java/SeCause/SeCause_be/domain/analysis/client/GithubRepositoryClient.javasrc/main/java/SeCause/SeCause_be/domain/analysis/code/AnalysisErrorCode.javasrc/main/java/SeCause/SeCause_be/domain/analysis/controller/AnalysisRequestApi.javasrc/main/java/SeCause/SeCause_be/domain/analysis/controller/AnalysisRequestController.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/GithubAccountResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/GithubBranchResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/GithubRepositoryResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/GithubUserAccountResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableGithubAccountListResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableGithubAccountResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableGithubAccountType.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryBranchListResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryBranchResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryListResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/dto/LinkableRepositoryResponse.javasrc/main/java/SeCause/SeCause_be/domain/analysis/service/AnalysisRequestService.javasrc/main/java/SeCause/SeCause_be/domain/analysis/validator/AnalysisRequestValidator.javasrc/main/java/SeCause/SeCause_be/domain/user/code/UserErrorCode.javasrc/main/java/SeCause/SeCause_be/domain/user/exception/UserException.javasrc/main/java/SeCause/SeCause_be/global/config/SwaggerConfig.javasrc/main/resources/application-dev.ymlsrc/main/resources/application-local.ymlsrc/main/resources/application.yml
💤 Files with no reviewable changes (2)
- .github/workflows/ci.yml
- .gitignore
| refresh-secret: ${REFRESH_SECRET} | ||
| refresh-token-hash-secret: ${REFRESH_TOKEN_HASH_SECRET} |
There was a problem hiding this comment.
JWT 리프레시 시크릿 환경변수 키가 다른 프로필과 불일치합니다.
Line [35]-Line [36] 키가 local 프로필(JWT_REFRESH_SECRET, JWT_REFRESH_HASH_SECRET)과 달라 배포 env 파일이 JWT_* 기준이면 dev 프로필에서 값 미주입으로 기동 실패할 수 있습니다.
제안 diff
- refresh-secret: ${REFRESH_SECRET}
- refresh-token-hash-secret: ${REFRESH_TOKEN_HASH_SECRET}
+ refresh-secret: ${JWT_REFRESH_SECRET}
+ refresh-token-hash-secret: ${JWT_REFRESH_HASH_SECRET}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/resources/application-dev.yml` around lines 35 - 36,
application-dev.yml uses environment variable keys refresh-secret and
refresh-token-hash-secret mapped to ${REFRESH_SECRET} and
${REFRESH_TOKEN_HASH_SECRET}, which are inconsistent with other profiles; update
these placeholders to use the JWT-prefixed env vars (replace ${REFRESH_SECRET}
with ${JWT_REFRESH_SECRET} and ${REFRESH_TOKEN_HASH_SECRET} with
${JWT_REFRESH_HASH_SECRET}) so the keys (refresh-secret,
refresh-token-hash-secret) read from the same JWT_* environment variables used
by other profiles.
| spring: | ||
| profiles: | ||
| active: local No newline at end of file |
There was a problem hiding this comment.
기본 설정에서 local 프로필 고정은 운영 오기동 위험이 큽니다.
Line [3]이 local로 고정되어 SPRING_PROFILES_ACTIVE 누락 시 운영 환경도 로컬 설정(JWT 로컬 기본값 포함)으로 기동될 수 있습니다. 기본 파일에서는 active를 고정하지 말고 런타임에서 명시적으로 주입하세요.
제안 diff
spring:
profiles:
- active: local
+ active: ${SPRING_PROFILES_ACTIVE}📝 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.
| spring: | |
| profiles: | |
| active: local | |
| spring: | |
| profiles: | |
| active: ${SPRING_PROFILES_ACTIVE} |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/resources/application.yml` around lines 1 - 3, Remove the hard-coded
spring.profiles.active: local default from application.yml so the app doesn't
fall back to the local profile when SPRING_PROFILES_ACTIVE is absent;
specifically, delete or unset the spring.profiles.active entry (the
"spring.profiles.active" key and its "local" value) and rely on
environment/property injection (SPRING_PROFILES_ACTIVE or
--spring.profiles.active) at runtime, or replace it with a non-binding
placeholder (e.g., leave it out or set to null) and document that profiles must
be provided when starting the app.
close #30
🔎 개요
연동할 레포지토리 목록 조회관련 API 구현했습니다.
📝 작업 내용
GET /analysis/request/accountsGET /analysis/request/repositoriesaccountName기준으로 개인 계정/organization 레포지토리 분기 처리keywordquery parameter로 레포지토리 이름 또는 owner 기준 검색GET /analysis/request/repositories/{owner}/{repository}/branches👀 변경 사항
기존 API 설계와 달라졌습니다. 기존에는 연동할 레포지토리 목록 조회 API 하나로 하려했으나, 흐름 상, 3개로 쪼개야할 거 같아 작업 내용과 같이 구현했습니다.
GitHub organization 및 private repository를 정상 조회하려면 OAuth 로그인 시 아래 scope가 필요합니다. (프론트한테 전달 완료)
📸 스크린샷 (Optional)
✅ 체크리스트
💬 고민사항 및 리뷰 요구사항 (Optional)
GitHub 레포지토리 검색은 GitHub Search API를 별도로 사용하지 않고, 선택한 계정/조직의 레포지토리 목록을 조회한 뒤 서버에서 keyword 기준으로 필터링하도록 구현했습니다. 현재 화면 흐름에서는 선택 계정 범위 내 검색이므로 이 방식이 API 응답 형태와 권한 처리를 단순하게 유지할 수 있다고 판단했습니다.
Summary by CodeRabbit
릴리스 노트
새 기능
개선