
OIDC에 대해서 학습하기 전에 인증, 인가에 대해서 먼저 알아보려고 한다.
| 구분 | 인증 (Authentication, AuthN) | 인가 (Authorization, AuthZ) |
|---|---|---|
| 정의 | 자신이 누구인지 신원을 증명하는 것 | 특정 리소스에 접근할 수 있는 권한을 부여하는 것 |
| 질문 | 당신은 누구입니까? | 당신은 이 일을 할 권한이 있습니까? |
| 수단 | ID/PW, 생체인식, OTP 등 | 토큰(JWT), 세션, ACL 등 |
| 순서 | 반드시 인가보다 먼저 수행됨 | 인증된 사용자를 대상으로 수행됨 |
1. 인증 단계
사용자가 로그인 정보(ID/PW)를 보낸다 -> 서버는 DB를 확인하여 "이 사람은 Elena가 맞다"라고 확인.
2. 인가 증서 발급
인증이 완료되면 서버는 Elena에게 '증서'(토큰이나 세션 ID)를 쥐어준다. 이 증서에는 "Elena는 '읽기' 권한이 있음" 같은 정보가 담겨있다.
3. 인가 단계
Elena가 게시물을 수정하려고 할 때, 서버는 Elena가 가진 '증서'를 보고 "너는 읽기 권한만 있는데 왜 수정을 해? 거부!"라고 판단한다.
OAuth 2.0 (인가 Focus): "구글에 있는 내 사진을 이 앱이 가져갈 수 있게 허락해줘"라는 권한 위임이 핵심 (인가)
OIDC (인증 Focus): OAuth 2.0 위에서 "이 사람이 구글의 어떤 사용자인지 정보를 줘"라는 신원 확인 기능을 더한 것 (인증)
인증과 인가를 실제로 구현할 때 개발자가 가장 고민하게 되는 지점은 사용자의 상태(State)를 어디에 저장할 것인가?
서버 메모리나 DB에 사용자의 로그인 상태를 유지하는 전통적인 방식
흐름: 로그인 성공 → 서버가 세션 ID 생성 및 저장 → 브라우저 쿠키에 세션 ID 저장 → 요청 시마다 쿠키 전송 → 서버가 세션 저장소에서 확인
장점
보안성: 실제 사용자 정보는 서버에 있고 ID만 주고받으므로 상대적으로 안전
제어권: 특정 사용자의 세션을 강제로 종료(로그아웃)시키기 쉬움
단점:
확장성(Scalability) 저하: 서버가 늘어나면 세션 정보를 공유하기 위해 별도의 Redis 같은 공유 저장소가 필요
서버 부하: 동시 접속자가 많을수록 서버 메모리 부담이 커짐
서버가 상태를 저장하지 않고, 필요한 정보를 토큰 자체에 담아 클라이언트에게 주는 방식
흐름: 로그인 성공 → 서버가 정보를 암호화한 토큰(JWT) 발급 → 클라이언트가 저장(LocalStorage 등) → 요청 시 헤더(Authorization)에 토큰 포함 → 서버는 토큰의 유효성만 검증
장점
확장성 우수: 서버가 상태를 저장하지 않으므로(Stateless), 어떤 서버로 요청이 가도 검증이 가능(MSA 구조에 적합)
무상태성: 서버 부하가 적고 별도의 세션 저장소가 필요 없음
단점
토큰 탈취 위험: 토큰 자체에 데이터가 담겨 있어 탈취 시 보안에 취약 (Payload는 누구나 볼 수 있음)
제어 불가: 한 번 발급된 토큰은 만료 전까지 서버에서 강제로 무효화하기 어려움
요즘은 OIDC나 OAuth 2.0을 사용할 때 JWT 기반의 토큰 방식을 주로 사용. 하지만 토큰 탈취 문제를 보완하기 위해 Access Token(짧은 수명)과 Refresh Token(긴 수명, DB 저장)을 혼합하여 세션의 '제어권'과 토큰의 '확장성' 사이에서 균형을 잡는 것이 일반적