ADR-04: OAuth 토큰 Graceful Degradation
| 날짜 | 작성자 | 리포지토리 |
|---|---|---|
| 2024-12-18 | @KubrickCode | collector |
배경
비공개 저장소 과제
저장소 분석 서비스는 공개 및 비공개 저장소 모두 지원해야 함:
공개 저장소:
- 인증 없이 접근 가능
- 모든 사용자 이용 가능
비공개 저장소:
- 사용자 인증 필요 (OAuth 토큰)
- 권한 있는 사용자만 접근 가능
설계 긴장
모든 분석에 인증을 요구하는 순진한 접근은 마찰을 만든다:
| 접근 방식 | 공개 저장소 | 비공개 저장소 | 사용자 경험 |
|---|---|---|---|
| 항상 인증 필요 | 동작 (하지만 불필요) | 동작 | 높은 마찰 |
| 인증 절대 없음 | 동작 | 실패 | 제한된 기능 |
| 가능할 때 인증 | 동작 | 권한 시 동작 | 최적 |
목표: 자격 증명이 있을 때 비공개 저장소 접근을 지원하면서 접근성을 최대화.
에러 처리 복잡성
토큰 관련 실패는 근본적으로 다른 원인을 가짐:
예상된 조건:
- 사용자가 계정 연결 안 함 (저장된 토큰 없음)
- 공개 전용 접근을 위해 토큰을 의도적으로 제공 안 함
인프라 실패:
- 토큰 저장소 서비스 불가
- 복호화 실패
- 토큰 조회 중 네트워크 타임아웃
이들은 다른 처리 전략이 필요함—모든 토큰 에러를 동일하게 처리하면 사용자를 불필요하게 차단하거나 실제 문제를 가림.
결정
명시적 에러 분류와 함께 OAuth 토큰 처리를 위한 graceful degradation 채택.
핵심 원칙
1. 도메인 예외 분리
예상된 조건과 인프라 실패 구분:
| 예외 유형 | 의미 | 처리 |
|---|---|---|
| Token Not Found | 저장된 토큰 없음 (예상됨) | 공개로 대체 |
| Token Lookup Failed | 인프라 에러 (예상치 못함) | 작업 실패 |
이것이 중요한 이유:
- 예상된 조건은 시스템 문제를 나타내지 않음
- 인프라 실패는 알림과 조사 필요
- 로그 레벨이 다름 (info vs error)
- 재시도 전략이 다름 (재시도 없음 vs 백오프로 재시도)
2. 공개 접근 대체
토큰이 없을 때 (예상된 조건):
- 비인증 접근으로 진행
- 관측성을 위해 info 레벨 로그
- 공개 저장소 정상 동작
- 비공개 저장소는 clone 시 실패 (예상됨)
3. 인프라 에러 시 빠른 실패
토큰 조회가 예상치 않게 실패할 때:
- 즉시 작업 실패
- error 레벨 로그
- 모니터링/알림 활성화
- 잠재적으로 손상된 상태로 진행 안 함
4. 선택적 토큰 조회
토큰 저장소 없는 배포 지원:
- 토큰 조회 미설정 시 공개 접근만 사용
- 공개 전용 사용 케이스를 위한 단순 배포 가능
- 미설정 컴포넌트에 대한 런타임 에러 없음
검토한 옵션
옵션 A: 예외 분리를 가진 Graceful Degradation (선택)
설명:
토큰 관련 에러를 예상됨 vs 예상치 못함으로 분류. 예상된 조건에는 공개 접근으로 대체, 인프라 에러는 실패.
장점:
- 공개 저장소를 위한 최적의 사용자 경험
- 명확한 에러 의미론으로 적절한 모니터링 가능
- 인증 및 비인증 사용 케이스 모두 지원
- 인프라 문제 즉시 표면화
단점:
- 더 복잡한 에러 처리 로직
- 신중한 예외 설계 필요
- 테스트가 여러 경로 커버 필요
옵션 B: 필수 인증
설명:
모든 분석 요청에 유효한 인증 필요.
토큰 없음 → 요청 거부
유효하지 않은 토큰 → 요청 거부장점:
- 단순한 로직 (토큰 필수, 끝)
- 모든 요청에 더 높은 속도 제한
- 일관된 동작
단점:
- 공개 저장소 분석만 원하는 사용자 차단
- 일반적인 사용 케이스에 불필요한 마찰
- 첫 사용 전 계정 연결 강제
옵션 C: 모든 토큰 에러를 치명적이지 않게 처리
설명:
모든 토큰 관련 에러에 공개 접근으로 대체.
토큰 없음 → 공개 접근
조회 실패 → 공개 접근
복호화 실패 → 공개 접근장점:
- 최대 가용성
- 단순한 대체 로직
단점:
- 인프라 문제 가림
- 복호화 실패가 보안 문제 나타낼 수 있음
- 알림/모니터링에서 차별화 없음
- 손상된 상태로 진행할 수 있음
구현 원칙
예외 계층
의도를 전달하는 도메인 예외 설계:
| 예외 | 의미 | 액션 |
|---|---|---|
| TokenNotFound | 토큰 없음 (비즈니스 조건) | Info 로그 + 대체 |
| TokenLookupFailed | 저장소/인프라 에러 (시스템 문제) | Error 로그 + 실패 |
토큰 처리 흐름
요청 도착
└── 토큰 조회 설정됨?
├── 아니오 → 공개 접근 사용
└── 예 → 토큰 조회 시도
├── 성공 → 인증된 접근 사용
├── 미발견 → 공개 접근 사용 (info)
└── 조회 실패 → 작업 실패 (error)암호화 고려사항
토큰이 암호화되어 저장될 때:
- 복호화 실패는 인프라 에러 ("토큰 미발견" 아님)
- 키 불일치는 설정 문제 나타냄
- 빠르게 실패해야 함, 조용히 저하되면 안 됨
로깅 전략
| 시나리오 | 레벨 | 내용 |
|---|---|---|
| 토큰 미발견 | INFO | 사용자 ID, 공개 접근으로 진행 |
| 토큰 발견 | DEBUG | 사용자 ID, 인증된 접근 사용 |
| 조회 실패 | ERROR | 사용자 ID, 에러 상세, 작업 실패 |
결과
긍정적
사용자 경험:
- 공개 저장소에 강제 인증 없음
- 자격 증명 있을 때 비공개 저장소 지원
- 누락된 자격 증명의 우아한 처리
운영 명확성:
- 예상된 조건과 에러 조건의 명확한 구분
- 적절한 알림 (예상된 조건에 거짓 경보 없음)
- 인프라 문제 즉시 표면화
유연성:
- 공개 전용 배포 지원
- 인증된 배포 지원
- 점진적 롤아웃 가능
보안:
- 복호화 실패가 조용히 저하되지 않음
- 토큰 저장소 문제가 플래그됨
- 에러 시 인증 우회 없음
부정적
복잡도:
- 하나 대신 두 가지 예외 유형
- 테스트할 여러 코드 경로
- 동작에 대한 문서 필요
잠재적 혼란:
- "토큰 미발견" vs "조회 실패" 구분 설명 필요
- 개발자가 올바른 예외 유형 선택 필요
- 로그 분석에 차이 이해 필요
조용한 저하 위험:
- 공개 대체는 일부 비공개 저장소 실패가 "예상됨"을 의미
- 사용자가 공개 제한에 도달했음을 인식 못할 수 있음
- 저하 발생 시 명확한 피드백 필요
참고 자료
- ADR-02: Clean Architecture 레이어 (도메인 예외 설계)
- ADR-01: 스케줄 기반 재수집 (스케줄러 컨텍스트에서의 토큰 처리)
