이번 작업을 통해 인증 정보가 없는 사용자에 대한 예외 처리를 완벽히 구현하고, API 명세서에 맞는 응답 포맷까지 정확히 출력되도록 개선했습니다. 이 글에서는 인증 예외 처리 흐름을 정리하고, 핵심 개념과 적용 포인트를 공유합니다.
인증 정보가 없는 사용자가
/task(예시) API를 호출할 경우
401 Unauthorized상태 코드와 함께 명세서에 정의된 JSON 응답을 반환해야 한다.
{
"status": "Failed",
"message": "[Unauthorized]Authorizer 정보가 없습니다."
}
401 UnauthorizedAWS API Gateway는 Cognito 등을 통해 인증을 수행한 후, 인증 결과를 Lambda로 전달합니다. 이 정보는 event.requestContext.authorizer 내부에 포함됩니다.
event = {
"requestContext": {
"authorizer": {
"user": "{\"sub\": \"...\", \"email\": \"...\"}", # 또는
"claims": { "sub": "...", "email": "..." }
}
}
}
다음과 같이 user나 claims 키가 없는 경우를 판단하여 인증 예외를 발생시킵니다.
authorizer = event.get("requestContext", {}).get("authorizer", {})
if "user" in authorizer:
...
elif "claims" in authorizer:
...
else:
raise AuthError("Authorizer 정보가 없습니다.")
일반 예외 (ValueError) | 커스텀 예외 (AuthError) |
|---|---|
| 단순하게 에러로 종료됨 | 명확한 응답 형식으로 반환됨 |
| 상태 코드 없음 | 401 Unauthorized 명확하게 설정됨 |
| 트레이스백 노출 가능성 | 사용자 친화적인 메시지 출력 가능 |
AuthError는 LambdaError를 상속하고 있어, 이후 예외 처리 핸들러에서 일관되게 처리할 수 있습니다.
예외가 발생하면, 다음과 같이 처리됩니다:
except Exception as e:
return handle_error(e)
핸들러 내부에서는 get_err_response() 등을 통해 명세서에 맞는 응답 포맷으로 변환해줍니다.
테스트에서는 인증 정보가 없는 상황을 다양한 방식으로 시뮬레이션했습니다:
authorizer를 아예 생략하거나 빈 객체로 설정claims는 존재하지만 sub 값이 없는 경우결과적으로, 다음을 검증했습니다:
401인지| 이유 | 설명 |
|---|---|
| 보안 강화 | 인증되지 않은 요청을 명확히 차단 |
| 사용자 경험 향상 | 실패 시 일관되고 명확한 메시지 전달 |
| 명세서 일치 | 프론트엔드 및 다른 팀과 협업 시 API 신뢰성 확보 |
| 유지보수 용이성 | 인증 방식이 변경되더라도 AuthError 클래스만 수정하면 대응 가능 |
| 문제 | 해결 방법 |
|---|---|
인증 정보가 없을 때 ValueError 발생 | AuthError 커스텀 예외로 대체 |
| 명세서에 맞는 에러 응답 포맷 부재 | handle_error() + get_err_response()로 통일된 응답 처리 |
| 응답 코드 불일치 및 메시지 부재 | 명확한 상태 코드(401)와 메시지 설정 |
claims가 있어도 내부 값이 비어있는 경우 | sub 키 존재 여부까지 체크 |
이제 이 인증 예외 처리 구조는 다른 모든 인증 기반 API에도 복사-붙여넣기만으로 재사용할 수 있는 견고한 패턴이 되었습니다. 추후 403 Forbidden, 409 Conflict 등 다른 인증/인가 관련 예외도 같은 방식으로 확장 가능합니다.