AWS Cognito 로그인 구현: User Pools vs Identity Pools 완전 정복

웹 앱에 회원가입과 로그인을 붙이려고 Cognito를 열었다가 'User Pools'와 'Identity Pools' 두 개가 보이는 순간 멈칫하게 된다. 이름도 비슷하고, 콘솔에서 나란히 있으니 같은 것처럼 보이지만 실제로는 완전히 다른 문제를 해결하는 서비스다. AWS Cognito User Pools로 사용자 데이터베이스를 관리하는 것이 일반적인 로그인 구현의 정답이다.

TL;DR — AWS Cognito User Pools vs Identity Pools

항목User PoolsIdentity Pools
핵심 역할사용자 디렉터리 (회원가입/로그인)AWS 리소스 접근 권한 위임
발급 토큰ID Token, Access Token, Refresh Token (JWT)임시 AWS 자격증명 (STS)
사용 시나리오앱 로그인, 사용자 프로필 관리S3 직접 업로드, DynamoDB 직접 접근
사용자 DB 관리✅ 직접 관리❌ 관리하지 않음
소셜 로그인 연동Google, Facebook, SAML 등 내장 지원User Pools 포함 외부 IdP 결과를 AWS 권한으로 교환

AWS Cognito의 두 구성요소가 동작하는 방식

User Pools는 말 그대로 사용자 데이터베이스다. 이메일/비밀번호, 전화번호, 소셜 계정으로 가입한 사용자 레코드를 저장하고, 인증 성공 시 JWT 토큰 세 개(ID Token, Access Token, Refresh Token)를 발급한다. 앱 서버나 API Gateway는 이 JWT를 검증해서 요청을 인가한다.

Identity Pools는 사용자를 저장하지 않는다. 대신 이미 인증된 사용자(User Pools JWT, Google OAuth 토큰, SAML Assertion 등)를 받아서 AWS STS로부터 임시 자격증명을 교환해준다. 브라우저에서 S3 버킷에 직접 파일을 올리거나, Lambda를 직접 호출해야 할 때 쓰는 레이어다.

User Pools는 '누구인가'를 증명하는 여권 발급소고, Identity Pools는 그 여권을 보고 AWS 건물 출입증을 발급해주는 보안 게이트다. 대부분의 웹 앱은 여권 발급소만 있으면 충분하다.
graph LR Browser["브라우저 / 앱"] UP["User Pool
(사용자 DB)"] IP["Identity Pool
(권한 브로커)"] STS["AWS STS"] APIGW["API Gateway
/ 앱 서버"] S3["S3 / DynamoDB
(AWS 리소스)"] Browser -->|"1. 로그인 요청"| UP UP -->|"2. JWT 발급"| Browser Browser -->|"3a. JWT 전달"| APIGW APIGW -->|"3a. 인가 처리"| Browser Browser -->|"3b. JWT 전달 (선택)"| IP IP -->|"4. 임시 자격증명 요청"| STS STS -->|"5. 임시 자격증명 반환"| IP IP -->|"6. 자격증명 전달"| Browser Browser -->|"7. 직접 접근"| S3
  1. 사용자 인증 흐름 (User Pools): 브라우저가 User Pool에 로그인 요청을 보내면 JWT 토큰이 반환된다. 이 토큰을 API Gateway나 앱 서버에 전달해 인가를 처리한다.
  2. AWS 리소스 직접 접근 흐름 (Identity Pools): User Pool JWT를 Identity Pool에 전달하면, Identity Pool이 STS에 임시 자격증명을 요청한다. 브라우저는 이 자격증명으로 S3나 DynamoDB에 직접 접근한다.
  3. 대부분의 웹 앱: API 서버가 AWS 리소스를 대신 호출하는 구조라면 User Pools만으로 충분하다. Identity Pools는 클라이언트가 AWS SDK를 직접 사용할 때 필요하다.

AWS Cognito User Pools로 로그인 구현하기

회원가입과 로그인이 목적이라면 User Pool 하나만 만들면 된다. 아래 단계를 순서대로 따라가면 프로덕션에서 쓸 수 있는 기본 구성이 완성된다.

Step 1: User Pool 생성

User Pool은 사용자 레코드를 담는 컨테이너다. 어떤 속성을 필수로 받을지, 비밀번호 정책은 어떻게 할지, MFA를 켤지 여기서 결정한다. 한번 생성하면 일부 설정(특히 필수 속성)은 변경이 불가능하므로 처음에 신중하게 설정해야 한다.

aws cognito-idp create-user-pool \
  --pool-name my-app-user-pool \
  --policies 'PasswordPolicy={MinimumLength=8,RequireUppercase=true,RequireLowercase=true,RequireNumbers=true,RequireSymbols=false}' \
  --auto-verified-attributes email \
  --username-attributes email \
  --mfa-configuration OFF \
  --region us-east-1

명령 실행 후 반환되는 UserPool.Id 값을 기록해둔다. 이후 모든 명령에서 이 ID가 필요하다.

Step 2: App Client 생성

User Pool 자체는 인증 엔드포인트가 아니다. 앱이 User Pool과 통신하려면 App Client가 필요하다. App Client는 어떤 인증 흐름을 허용할지, 클라이언트 시크릿을 사용할지 결정한다. 브라우저 기반 SPA나 모바일 앱은 클라이언트 시크릿을 안전하게 보관할 수 없으므로 시크릿 없이 생성하는 것이 일반적이다.

aws cognito-idp create-user-pool-client \
  --user-pool-id us-east-1_XXXXXXXXX \
  --client-name my-app-client \
  --no-generate-secret \
  --explicit-auth-flows ALLOW_USER_SRP_AUTH ALLOW_REFRESH_TOKEN_AUTH \
  --region us-east-1

반환되는 UserPoolClient.ClientId를 프론트엔드 설정에 사용한다. ALLOW_USER_SRP_AUTH는 비밀번호를 평문으로 전송하지 않는 SRP(Secure Remote Password) 프로토콜을 활성화한다.

Step 3: 사용자 가입 및 확인 테스트

CLI로 전체 가입 흐름을 검증할 수 있다. 이메일 인증 코드가 실제로 발송되는지, 확인 후 로그인이 되는지 프론트엔드 연동 전에 확인해두면 디버깅 시간이 줄어든다.

# 사용자 가입 (이메일로 인증 코드 발송됨)
aws cognito-idp sign-up \
  --client-id YOUR_CLIENT_ID \
  --username user@example.com \
  --password 'MyP@ssw0rd' \
  --user-attributes Name=email,Value=user@example.com \
  --region us-east-1

# 이메일로 받은 코드로 계정 확인
aws cognito-idp confirm-sign-up \
  --client-id YOUR_CLIENT_ID \
  --username user@example.com \
  --confirmation-code 123456 \
  --region us-east-1

Step 4: 로그인 및 JWT 토큰 획득

SRP 인증 흐름은 CLI로 직접 테스트하기 복잡하므로, 관리자 권한 인증 흐름(ADMIN_USER_PASSWORD_AUTH)으로 토큰을 확인할 수 있다. 단, 이 흐름은 서버 사이드에서만 사용해야 하며 App Client에 명시적으로 허용해야 한다.

aws cognito-idp admin-initiate-auth \
  --user-pool-id us-east-1_XXXXXXXXX \
  --client-id YOUR_CLIENT_ID \
  --auth-flow ADMIN_USER_PASSWORD_AUTH \
  --auth-parameters USERNAME=user@example.com,PASSWORD='MyP@ssw0rd' \
  --region us-east-1

성공하면 AuthenticationResult 아래에 IdToken, AccessToken, RefreshToken이 반환된다. IdToken은 사용자 속성(이메일, sub 등)을 담은 JWT이고, AccessToken은 User Pool API 호출 권한을 담는다.

Identity Pools가 실제로 필요한 경우

프론트엔드에서 AWS SDK를 직접 호출해야 할 때 Identity Pools가 등장한다. 예를 들어 사용자가 브라우저에서 직접 S3에 이미지를 업로드하거나, IoT 디바이스가 AWS 서비스를 직접 호출하는 시나리오다. 이 경우 User Pool에서 받은 JWT를 Identity Pool에 전달해 임시 AWS 자격증명으로 교환한다.

Identity Pool 생성 및 User Pool 연동

🔽 Identity Pool 생성 CLI 펼치기
# Identity Pool 생성
aws cognito-identity create-identity-pool \
  --identity-pool-name my-app-identity-pool \
  --cognito-identity-providers ProviderName=cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXXX,ClientId=YOUR_CLIENT_ID,ServerSideTokenCheck=true \
  --region us-east-1

# 반환된 IdentityPoolId를 기록
# 예: us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

# 인증된 사용자에게 부여할 IAM 역할 연결
aws cognito-identity set-identity-pool-roles \
  --identity-pool-id us-east-1:YOUR_IDENTITY_POOL_ID \
  --roles authenticated=arn:aws:iam::123456789012:role/CognitoAuthenticatedRole \
  --region us-east-1

Identity Pool에 연결하는 IAM 역할(CognitoAuthenticatedRole)에는 실제로 필요한 AWS 리소스 권한만 부여해야 한다. 예를 들어 특정 S3 버킷의 특정 prefix에만 쓰기 권한을 주는 식으로 최소 권한 원칙을 적용한다.

실제 운영에서 마주치는 함정 — 잘못된 진단 패턴

처음 Cognito를 붙일 때 가장 흔한 실수는 'Identity Pools도 사용자 로그인을 처리한다'는 오해다. 콘솔에서 Identity Pool을 먼저 만들고, 거기서 사용자를 관리하려다가 사용자 레코드가 어디에도 저장되지 않는다는 걸 뒤늦게 발견한다.

증상은 이렇다. Identity Pool로 Google 소셜 로그인을 연동했는데, 로그인한 사용자 목록을 어디서도 조회할 수 없다. CloudWatch 로그에는 인증 성공이 찍히고, STS 자격증명도 정상 발급된다. 그런데 '가입한 사용자가 몇 명인지' 알 방법이 없다.

원인은 Identity Pool이 사용자 레코드를 저장하지 않기 때문이다. Identity Pool은 외부 토큰을 AWS 자격증명으로 교환하는 브로커일 뿐이다. 사용자 프로필, 가입 일시, 이메일 주소를 관리하려면 User Pool이 반드시 필요하다. 소셜 로그인도 User Pool의 'Federated Identity' 기능으로 연동하면 사용자 레코드가 User Pool에 생성된다.

graph TD subgraph WRONG ["❌ 잘못된 구성 — 사용자 레코드 없음"] W_Browser["브라우저"] W_IP["Identity Pool만 사용"] W_STS["STS 자격증명 발급"] W_Note["사용자 DB 없음
조회 불가"] W_Browser --> W_IP --> W_STS W_IP -.->|"저장 안 됨"| W_Note end subgraph RIGHT ["✅ 올바른 구성 — User Pool 중심"] R_Browser["브라우저"] R_UP["User Pool
(사용자 레코드 저장)"] R_JWT["JWT 발급"] R_IP["Identity Pool
(선택적 추가)"] R_Browser --> R_UP --> R_JWT R_JWT -.->|"필요 시"| R_IP end
  1. 잘못된 구성: Identity Pool만 사용하면 AWS 자격증명은 발급되지만 사용자 레코드가 어디에도 저장되지 않는다.
  2. 올바른 구성: User Pool이 사용자 레코드를 관리하고 JWT를 발급한다. Identity Pool은 선택적으로 그 JWT를 AWS 자격증명으로 교환하는 역할만 한다.
  3. 소셜 로그인: Google/Facebook 연동도 User Pool 레벨에서 처리하면 소셜 계정 사용자도 User Pool에 레코드가 생성된다.

User Pool 사용자 조회 및 관리 CLI

운영 중에 자주 쓰는 사용자 관리 명령어들이다. 특정 사용자 상태 확인, 강제 비밀번호 변경, 계정 비활성화 등을 API로 처리할 수 있다.

# 사용자 목록 조회
aws cognito-idp list-users \
  --user-pool-id us-east-1_XXXXXXXXX \
  --region us-east-1

# 특정 사용자 상세 조회
aws cognito-idp admin-get-user \
  --user-pool-id us-east-1_XXXXXXXXX \
  --username user@example.com \
  --region us-east-1

# 사용자 계정 비활성화
aws cognito-idp admin-disable-user \
  --user-pool-id us-east-1_XXXXXXXXX \
  --username user@example.com \
  --region us-east-1

# 사용자 강제 로그아웃 (모든 세션 무효화)
aws cognito-idp admin-user-global-sign-out \
  --user-pool-id us-east-1_XXXXXXXXX \
  --username user@example.com \
  --region us-east-1

API Gateway와 User Pool 통합 — JWT 인가 설정

User Pool에서 발급한 JWT를 API Gateway에서 검증하도록 설정하면 백엔드 서버에서 별도의 토큰 검증 로직이 필요 없다. API Gateway가 요청 헤더의 JWT를 자동으로 검증하고, 유효하지 않으면 401을 반환한다.

# HTTP API에 JWT Authorizer 생성
aws apigatewayv2 create-authorizer \
  --api-id YOUR_API_ID \
  --authorizer-type JWT \
  --identity-source '$request.header.Authorization' \
  --name cognito-authorizer \
  --jwt-configuration Audience=YOUR_CLIENT_ID,Issuer=https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXXX \
  --region us-east-1

이 설정 후 API 라우트에 이 Authorizer를 연결하면, 클라이언트는 Authorization: Bearer <IdToken> 헤더를 포함해야 한다. JWT의 sub 클레임이 요청 컨텍스트에 자동으로 주입되므로 Lambda에서 event.requestContext.authorizer.jwt.claims.sub로 사용자 ID를 바로 읽을 수 있다.

AWS Cognito 로그인 구현 마무리 및 다음 단계

회원가입과 로그인이 목적이라면 User Pools가 정답이다. Identity Pools는 인증된 사용자에게 AWS 리소스 직접 접근 권한을 줄 때만 추가로 고려한다. 두 서비스를 함께 쓰는 경우에도 User Pool이 항상 먼저 존재해야 한다.

다음 단계로는 Cognito Hosted UI를 활용한 소셜 로그인 연동, Amplify 라이브러리를 통한 프론트엔드 통합, 그리고 고급 보안 기능(어드밴스드 시큐리티, 위협 감지)을 검토해볼 수 있다. 공식 문서는 AWS Cognito 개발자 가이드를 참고한다.

핵심 용어 정리

용어설명
User PoolCognito의 사용자 디렉터리. 가입/로그인 처리 및 JWT 발급을 담당한다.
Identity Pool외부 인증 토큰을 AWS STS 임시 자격증명으로 교환해주는 브로커.
JWT (JSON Web Token)User Pool 인증 성공 시 발급되는 서명된 토큰. ID Token, Access Token, Refresh Token 세 종류.
App ClientUser Pool과 통신하는 애플리케이션 단위 식별자. 인증 흐름 및 허용 범위를 설정한다.
SRP (Secure Remote Password)비밀번호를 평문으로 전송하지 않는 인증 프로토콜. Cognito 권장 인증 흐름.

Related Posts

댓글

이 블로그의 인기 게시물

EC2 SSH 연결 타임아웃 완전 해결 가이드: Security Group 인바운드 규칙부터 라우팅까지

EC2 SSH 연결 시간 초과: 확인해야 할 보안 그룹(Security Group) 규칙

IAM User vs IAM Role 차이점 완전 정리 — EC2에서 S3 접근 시 무엇을 써야 하는가