Skip to content

fix: 실패 원인별로 HTTP 상태코드를 구분해 응답 - #6

Merged
anonymousRecords merged 1 commit into
mainfrom
fix/error-status-codes
Aug 29, 2026
Merged

fix: 실패 원인별로 HTTP 상태코드를 구분해 응답#6
anonymousRecords merged 1 commit into
mainfrom
fix/error-status-codes

Conversation

@anonymousRecords

Copy link
Copy Markdown
Owner

변경 사항

/api/[username]/animation의 모든 실패가 500으로 뭉개지던 것을 원인별로 구분했습니다.

실패 상황 이전 이후
존재하지 않는 GitHub 사용자 500 404
GitHub API 호출 실패 (HTTP 오류, NOT_FOUND 외 GraphQL 에러) 500 502
GITHUB_TOKEN 미설정 500 500
그 외 (렌더링 실패 등) 500 500

왜 필요한가

#4에서 겪은 상황이 정확히 이 문제였습니다. 의존하던 외부 API가 사라졌는데 응답이 500 Internal Server Error 한 줄뿐이라, 우리 코드 결함인지 업스트림 장애인지 서버 로그를 봐야만 구분할 수 있었습니다. 502가 분리되면 상태코드만으로 판단됩니다.

구현

에러 메시지 문자열로 분기하면 문구를 바꾸는 순간 조용히 깨지므로, 타입으로 구분했습니다.

export class UserNotFoundError extends Error {}   // → 404
export class GitHubApiError extends Error {}      // → 502
export class MissingTokenError extends Error {}   // → 500

존재하지 않는 사용자는 HTTP 404가 아니라 200 응답의 GraphQL errors 배열로 도착합니다. 실제 응답을 확인해 type 필드로 분기했습니다:

{"data":{"user":null},
 "errors":[{"type":"NOT_FOUND","message":"Could not resolve to a User with the login of '...'"}]}

따라서 type === "NOT_FOUND"UserNotFoundError, 나머지 GraphQL 에러는 업스트림 문제로 보아 GitHubApiError로 분류합니다.

에러 응답에는 캐시 헤더를 붙이지 않습니다. 성공 응답이 s-maxage=86400이라, 오타 친 사용자명이 하루 동안 캐시되면 곤란합니다.

변경 유형

  • 버그 수정 (기존 기능을 수정하는 non-breaking change)
  • 새 기능 (기존 기능을 유지하면서 추가되는 non-breaking change)
  • Breaking change (기존 기능에 영향을 주는 변경)
  • 문서 업데이트

관련 이슈

없음

테스트 방법

네 경로 모두 로컬 dev 서버에서 실제로 유도해 확인했습니다. 수정 전 전부 500임을 먼저 확인했습니다.

경로 유도 방법 수정 전 수정 후
없는 사용자 존재하지 않는 username 요청 500 404 GitHub user not found: ...
GitHub API 실패 GITHUB_TOKEN=ghp_invalid... 로 기동 → 401 500 502 Failed to reach the GitHub API
토큰 미설정 GITHUB_TOKEN 없이 기동 500 500 Internal Server Error
정상 (회귀 확인) 유효 토큰 + 실제 사용자 200 200 image/png

기존 검증 스크립트도 재실행했습니다 — 컨트리뷰션 조회(371일/1633커밋), 마크다운 생성 5/5 모두 통과.

체크리스트

  • 코드가 프로젝트 스타일 가이드를 따름
  • 셀프 코드 리뷰 완료
  • 필요한 경우 문서 업데이트
  • pnpm lint 통과 (49개 파일)
  • pnpm build 통과 (exit 0)

스크린샷 (UI 변경 시)

UI 변경 없음 (API 응답 코드만 변경).

🤖 Generated with Claude Code

https://claude.ai/code/session_01La1oXcrwEZycnLJGdkFn3y

지금까지 모든 실패가 500으로 뭉개져, 사용자 오타인지 GitHub 장애인지
배포 설정 오류인지 로그를 봐야만 알 수 있었다.

에러 메시지 문자열로 분기하면 문구 변경에 깨지므로 타입을 도입했다.

- UserNotFoundError → 404. GraphQL errors의 type이 NOT_FOUND인 경우와
  data.user가 null인 경우를 여기에 매핑한다.
- GitHubApiError → 502. HTTP 실패와 NOT_FOUND 외 GraphQL 에러.
  업스트림 장애를 우리 쪽 오류(500)와 구분하기 위함이다.
- MissingTokenError → 500. 배포 설정 오류이므로 서버 오류가 맞다.

에러 응답에는 캐시 헤더를 붙이지 않는다. 성공 응답은 s-maxage=86400이라
오타 친 사용자명이 하루 동안 캐시되면 곤란하다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01La1oXcrwEZycnLJGdkFn3y
@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
git-style Ready Ready Preview Aug 29, 2026 9:17am

@anonymousRecords
anonymousRecords merged commit cc0aba3 into main Aug 29, 2026
3 checks passed
@anonymousRecords
anonymousRecords deleted the fix/error-status-codes branch August 29, 2026 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant