웹·모바일 앱을 만들다 보면 거의 모든 개발자가 같은 순서로 같은 함정에 빠진다. 처음엔 사용자 테이블에 비밀번호를 직접 저장한다(평문으로). 그러다 해싱을 배워 bcrypt를 쓴다. 그다음 비밀번호 재설정, 이메일 검증, MFA, 소셜 로그인, 토큰 만료, 리프레시 토큰 회전을 차례로 구현하다가 "이걸 왜 내가 다 만들고 있지?"라는 깨달음에 도달한다. 인증(authentication, 너는 누구냐)과 인가(authorization, 너는 뭘 할 수 있냐)는 보안의 가장 깨지기 쉬운 영역이고, 직접 만든 인증 시스템은 거의 항상 어딘가에 구멍이 있다. Amazon Cognito는 이 "직접 만들지 마라" 영역을 통째로 관리형으로 가져간 서비스다.
Cognito가 DVA-C02 시험에서 까다로운 이유는 두 개의 별개 구성요소(User Pool과 Identity Pool) 가 비슷한 이름으로 헷갈리게 공존하기 때문이다. 둘은 푸는 문제가 완전히 다르다 — User Pool은 "로그인을 처리하고 신분증(JWT)을 발급"하고, Identity Pool은 "그 신분증을 AWS 리소스 출입증(IAM 임시 자격증명)으로 교환"한다. 이 분리를 이해하면 Cognito 문제의 대부분이 풀린다. 이번 글은 왜 둘이 나뉘었는지, JWT 세 종류가 각각 무슨 역할인지, 그리고 Lambda 트리거로 인증 흐름을 어떻게 확장하는지를 본다.