Skip to content

Conversation

@kamillcream
Copy link
Contributor

@kamillcream kamillcream commented Aug 9, 2025

📌 PR 개요

  • try-catch가 누락된 함수에 try-catch 적용 + 에러 발생 시 메시지 반환이 아니라 예외를 던지고 호출 서비스에서 예외 메시지를 디스코드로 전송

✅ 변경사항

  • try-catch 적용
  • catch 절에서 메시지 return 제거

🔍 체크리스트

  • PR 제목은 명확한가요?
  • 관련 이슈가 있다면 연결했나요?
  • 로컬 테스트는 통과했나요?
  • 코드에 불필요한 부분은 없나요?

📎 관련 이슈

Closes #16


💬 기타 참고사항

Summary by CodeRabbit

  • 버그 수정

    • 다양한 봇 명령어 처리 과정에서 발생하는 예외를 포착하여, 오류 발생 시 사용자에게 명확한 에러 메시지를 제공합니다.
    • Google Cloud API 연동 과정에서 오류 발생 시, 상세한 예외 메시지로 안내하도록 개선되었습니다.
  • 기타

    • CI/CD 파이프라인이 특정 브랜치에서만 동작하도록 워크플로우 트리거가 변경되었습니다.

@kamillcream kamillcream self-assigned this Aug 9, 2025
@kamillcream kamillcream added in: api API 관련 status: needs feedback 리뷰어 또는 담당자의 피드백이 필요한 상태입니다. priority: medium 일반적인 우선순위의 작업입니다. type: bug 버그를 수정하는 작업입니다. labels Aug 9, 2025
@kamillcream kamillcream linked an issue Aug 9, 2025 that may be closed by this pull request
2 tasks
@coderabbitai
Copy link

coderabbitai bot commented Aug 9, 2025

Walkthrough

이번 변경에서는 Discord 봇의 GCP 관련 명령 처리 로직과 GCP 서비스 내부에서 발생하는 예외를 포괄적으로 try-catch로 감싸고, 예외 발생 시 사용자에게 명확한 에러 메시지를 출력하도록 개선하였습니다. 또한 CI/CD 워크플로우 트리거 브랜치가 main에서 fix/#16-exception-handling-fix로 변경되었습니다.

Changes

Cohort / File(s) Change Summary
Discord 명령 예외 처리 개선
src/main/java/com/gcp/domain/discord/service/GcpBotService.java
모든 주요 서브커맨드("start", "stop", "logs", "list", "create", "firewall-list", "firewall-create", "firewall-delete")에 try-catch 추가. 예외 발생 시 사용자에게 에러 메시지로 응답하도록 수정. 기존 로직은 유지.
GCP 서비스 예외 처리 개선
src/main/java/com/gcp/domain/gcp/service/GcpService.java
GCP API 호출 실패 시 에러 메시지 반환 대신 RuntimeException을 throw하도록 모든 메소드 내부 로직 수정. 일부 메소드에서 try-catch 추가 및 불필요한 import 정리.
CI/CD 워크플로우 트리거 브랜치 변경
.github/workflows/deploy.yml
워크플로우 트리거 브랜치를 main에서 fix/#16-exception-handling-fix로 변경. 나머지 워크플로우 내용은 변경 없음.

Sequence Diagram(s)

sequenceDiagram
    participant DiscordUser
    participant GcpBotService
    participant GcpService

    DiscordUser->>GcpBotService: 슬래시 커맨드 실행 (예: start, stop 등)
    GcpBotService->>GcpService: GCP API 호출 (try-catch로 감싸짐)
    GcpService-->>GcpBotService: 성공 결과 또는 예외 throw
    alt 예외 발생 시
        GcpBotService-->>DiscordUser: "❌" + 에러 메시지로 응답
    else 정상 처리
        GcpBotService-->>DiscordUser: 정상 결과 메시지 응답
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Assessment against linked issues

Objective Addressed Explanation
orElseThrow 대신 값이 있나 확인 후 없으면 대체 메시지 출력 (#16)
try-catch로 GCP API 호출 함수 감싸기 (#16)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
CI/CD 워크플로우 트리거 브랜치 변경 (.github/workflows/deploy.yml) 예외 처리 개선(#16)과 직접적으로 관련 없는 CI/CD 브랜치 트리거 변경이 포함됨.

Poem

예외가 와도 이제는 걱정 마세요 🐰
봇이 친절하게 알려줄게요,
GCP 호출이 실패해도,
"❌" 메시지로 안내해요!
리뷰어님, 안심하고 커맨드 날려보세요~
오늘도 코드는 한층 더 튼튼해졌답니다!

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/#16-exception-handling-fix

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • 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.
  • 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.

Support

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

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 for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for 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 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 for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 2

🔭 Outside diff range comments (1)
src/main/java/com/gcp/domain/gcp/service/GcpService.java (1)

44-45: Optional 값 미존재 시 상세 메시지 누락

orElseThrow()에 아무 메시지도 전달하지 않아 토큰이 없을 때 NoSuchElementException이 빈 메시지로 던져집니다. 호출측에 의미 있는 정보를 주기 위해 커스텀 예외나 orElseThrow(() -> new RuntimeException("Google OAuth 토큰을 찾을 수 없습니다.")) 형태로 명시적 메시지를 포함해 주세요.

♻️ Duplicate comments (1)
src/main/java/com/gcp/domain/discord/service/GcpBotService.java (1)

197-221: deferReply() 후 catch 블록에서 reply() 사용

앞서 지적한 것과 동일한 문제입니다. 모든 deferReply() 블록의 예외 처리에서 reply() 대신 getHook() 사용으로 수정해 주세요.

🧹 Nitpick comments (3)
src/main/java/com/gcp/domain/gcp/service/GcpService.java (1)

186-190: @SneakyThrows 불필요

이 메서드는 내부에서 모든 예외를 catch하고 있으므로 Checked 예외 전파가 없습니다. @SneakyThrows를 제거해도 컴파일이 통과하니 어노테이션을 삭제해 코드 가독성을 높여주세요.

src/main/java/com/gcp/domain/discord/service/GcpBotService.java (2)

129-135: 불필요한 이중 세미콜론

event.reply("❌ " + e.getMessage()).queue();; 처럼 세미콜론이 두 번 들어가 있습니다. 빌드에는 영향 없지만 제거하여 가독성을 높여주세요.


170-175: 빈 리스트 상황에서 예외 사용

VM이 없을 때 Exception을 던지고 여기서 잡아 “보유 중인 인스턴스가 없습니다.”를 응답하고 있습니다. 단순 비즈니스 결과를 예외로 표현하기보다 서비스 메서드가 빈 리스트를 반환하도록 하고 봇에서 그대로 메시지를 보여주는 편이 명확합니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bd99bd0 and c9ed4c8.

📒 Files selected for processing (3)
  • .github/workflows/deploy.yml (1 hunks)
  • src/main/java/com/gcp/domain/discord/service/GcpBotService.java (2 hunks)
  • src/main/java/com/gcp/domain/gcp/service/GcpService.java (12 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: kamillcream
PR: Cloudible/GCP#8
File: src/main/java/com/gcp/domain/gcp/service/GcpService.java:38-38
Timestamp: 2025-08-01T19:45:32.212Z
Learning: Discord 봇 서비스에서는 orElseThrow()로 예외를 던지는 것보다 Optional.isEmpty() 체크 후 사용자 친화적인 메시지를 직접 반환하는 것을 선호함. 특히 GcpService.java에서 Google OAuth 토큰 조회 실패 시 예외 대신 안내 메시지 반환이 더 적절함.
📚 Learning: 2025-08-01T19:45:32.212Z
Learnt from: kamillcream
PR: Cloudible/GCP#8
File: src/main/java/com/gcp/domain/gcp/service/GcpService.java:38-38
Timestamp: 2025-08-01T19:45:32.212Z
Learning: Discord 봇 서비스에서는 orElseThrow()로 예외를 던지는 것보다 Optional.isEmpty() 체크 후 사용자 친화적인 메시지를 직접 반환하는 것을 선호함. 특히 GcpService.java에서 Google OAuth 토큰 조회 실패 시 예외 대신 안내 메시지 반환이 더 적절함.

Applied to files:

  • src/main/java/com/gcp/domain/discord/service/GcpBotService.java
  • src/main/java/com/gcp/domain/gcp/service/GcpService.java
🔇 Additional comments (3)
src/main/java/com/gcp/domain/gcp/service/GcpService.java (2)

268-271: 루프 중 한 프로젝트 실패 시 전체 중단

for 루프 안에서 한 프로젝트 조회가 실패하면 RuntimeException을 던져 전체 목록 조회가 중단됩니다. 장애가 난 프로젝트를 로그로만 남기고 continue로 넘어가면 나머지 프로젝트 정보는 제공할 수 있습니다. 실패 허용(soft‐fail)이 더 적합한지 검토해 주세요.


372-375: 에러 응답 형식 불일치

Conflict 시에는 문자열을 반환하면서 그 외 예외는 throw 하고 있습니다. 호출 측(GcpBotService)에서는 패턴이 혼재되어 처리 로직이 복잡해집니다. 동일한 기준(전부 예외, 혹은 전부 메시지 반환)으로 맞춰주세요.

.github/workflows/deploy.yml (1)

5-5: 메인 브랜치 배포 누락 가능성

배포 트리거가 fix/#16-exception-handling-fix 로 한정되어 있어 PR 병합 후 main 브랜치에서 CI/CD가 동작하지 않을 수 있습니다. 이후 운영 배포를 위해 main도 포함하거나 branches-ignore 패턴을 사용하는 방안을 검토하세요.

Comment on lines +146 to 162
try{
String vmName = getRequiredOption(event, "vm_name");
event.deferReply().queue();

List<String> logs = gcpService.getVmLogs(userId, guildId, vmName);
List<String> logs = gcpService.getVmLogs(userId, guildId, vmName);

if (logs.isEmpty()) {
event.getHook().sendMessage("📭 로그가 없습니다.").queue();
return;
}
if (logs.isEmpty()) {
event.getHook().sendMessage("📭 로그가 없습니다.").queue();
return;
}

for (String log : logs) {
event.getHook().sendMessage("```bash\n" + log + "\n```").queue();
for (String log : logs) {
event.getHook().sendMessage("```bash\n" + log + "\n```").queue();
}
} catch (RuntimeException e){
event.reply("❌ " + e.getMessage()).queue();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

deferReply() 이후 오류 응답 방식 오류

event.deferReply() 호출 후에는 event.reply()를 다시 사용할 수 없습니다. 예외 발생 시

event.getHook().sendMessage("❌ " + e.getMessage()).queue();

또는 editOriginal()로 응답을 수정해야 합니다. 동일 패턴이 firewall-list 등 다른 커맨드에도 있으니 함께 수정해 주세요.

🤖 Prompt for AI Agents
In src/main/java/com/gcp/domain/discord/service/GcpBotService.java around lines
146 to 162, after calling event.deferReply(), the code incorrectly uses
event.reply() in the catch block, which is not allowed. To fix this, replace
event.reply() with event.getHook().sendMessage() or use
event.getHook().editOriginal() to send the error message. Also, review and apply
the same fix to other commands like firewall-list that use this pattern.

Comment on lines +55 to 57
log.error("VM 시작 오류", e);
throw new RuntimeException("Compute API (start) 호출 도중 에러 발생: ", e);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

중복적인 RuntimeException 래핑 패턴

모든 메서드에서 동일한 패턴으로 예외를 잡아 RuntimeException으로 다시 래핑하고 있습니다.

  • 예외 유형별로 구분이 사라져 상위 계층에서 세밀한 분기 처리가 어렵습니다.
  • 메시지가 한글 + 영문 혼용으로 중복되고 있어 유지보수가 힘듭니다.

서비스 전용 GcpApiException 같은 커스텀 런타임 예외를 정의하여 공통 정보를 담고, 필요 시 errorCode를 포함하도록 리팩터링을 권장합니다.

Also applies to: 76-79, 102-105, 169-172, 181-183, 198-204, 227-230, 268-271, 373-375, 418-420, 460-461, 486-487

🤖 Prompt for AI Agents
In src/main/java/com/gcp/domain/gcp/service/GcpService.java around lines 55-57
and similarly at lines 76-79, 102-105, 169-172, 181-183, 198-204, 227-230,
268-271, 373-375, 418-420, 460-461, and 486-487, the code repeatedly catches
exceptions and wraps them in RuntimeException with mixed language messages,
causing poor exception granularity and maintenance difficulty. Define a custom
runtime exception class named GcpApiException that can hold common error
information and optionally an errorCode. Replace all RuntimeException wrapping
with this custom exception, unify the error messages into a consistent format,
and use the custom exception to improve error handling and maintainability.

@kamillcream kamillcream merged commit f4b62b7 into main Aug 10, 2025
3 of 5 checks passed
@kamillcream kamillcream deleted the fix/#16-exception-handling-fix branch August 10, 2025 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in: api API 관련 priority: medium 일반적인 우선순위의 작업입니다. status: needs feedback 리뷰어 또는 담당자의 피드백이 필요한 상태입니다. type: bug 버그를 수정하는 작업입니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[fix] 예외 처리 개선

2 participants