HTTP Basic Auth부터 토큰 기반 인증, 패스키까지 인증과 권한 관리의 역사를 짚어보고, 아이덴티티와 인증, 인가의 개념을 명확히 구분합니다.
소프트웨어 시스템에서 "너는 누구인가?"와 "너는 무엇을 할 수 있는가?"라는 질문은 가장 근본적인 보안 과제입니다. 수십 년에 걸쳐 이 질문에 답하는 방식은 극적으로 변화해 왔습니다. 이 시리즈의 첫 번째 장에서는 인증과 권한 관리가 어떻게 진화해 왔는지 살펴보고, 현대 시스템이 직면한 도전 과제를 정리합니다.
인증(Authentication) 메커니즘은 웹과 분산 시스템의 발전과 함께 네 가지 큰 세대를 거쳤습니다.
1990년대 웹의 초창기, 인증은 매우 단순했습니다. HTTP Basic Auth는 사용자 이름과 비밀번호를 Base64로 인코딩하여 매 요청마다 헤더에 포함시키는 방식이었습니다.
GET /api/resource HTTP/1.1
Host: example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=Base64는 암호화가 아닙니다. 단순 인코딩에 불과하므로 네트워크를 스니핑하면 자격 증명이 그대로 노출됩니다. HTTPS 없이 Basic Auth를 사용하는 것은 비밀번호를 평문으로 전송하는 것과 다름없습니다.
Basic Auth의 치명적 한계는 명확했습니다. 매 요청마다 자격 증명을 전송해야 하고, 로그아웃 메커니즘이 없으며, 브라우저 캐시에 자격 증명이 저장되는 보안 문제가 있었습니다. 하지만 그 단순함 덕분에 내부 시스템이나 간단한 API에서는 지금도 사용되고 있습니다.
웹 애플리케이션이 복잡해지면서 세션 기반 인증(Session-based Authentication)이 등장했습니다. 서버가 상태(state)를 유지하는 방식으로, 사용자가 한 번 로그인하면 서버가 세션을 생성하고 세션 ID를 쿠키로 내려주는 구조입니다.
세션 기반 인증은 오랜 기간 웹 인증의 표준이었지만, 분산 시스템 환경에서 근본적인 한계를 드러냈습니다.
2010년대에 접어들면서 JWT(JSON Web Token)를 중심으로 한 토큰 기반 인증이 급부상했습니다. 서버가 상태를 유지하지 않는 스테이트리스(Stateless) 구조로, 마이크로서비스와 모바일 환경에 적합했습니다.
// JWT는 세 부분으로 구성: Header.Payload.Signature
const token = [
// Header: 알고리즘과 토큰 타입
btoa(JSON.stringify({ alg: "RS256", typ: "JWT" })),
// Payload: 클레임 (사용자 정보, 만료 시간 등)
btoa(JSON.stringify({
sub: "user-123",
name: "홍길동",
roles: ["admin"],
iat: 1719900000,
exp: 1719903600,
})),
// Signature: Header + Payload를 비밀키로 서명
"서명값"
].join(".");토큰 기반 인증은 OAuth 2.0과 함께 폭발적으로 성장했습니다. 서드파티 애플리케이션에 제한된 접근 권한을 위임할 수 있게 되면서, 소셜 로그인과 API 생태계가 꽃피웠습니다.
현재 진행 중인 4세대 인증은 비밀번호 자체를 제거하는 방향으로 진화하고 있습니다. 패스키(Passkeys)와 WebAuthn이 대표적이며, 생체 인식과 하드웨어 보안 키를 활용하여 피싱에 면역인 인증을 구현합니다.
보안 설계에서 가장 흔한 혼동은 아이덴티티(Identity), 인증(Authentication), 인가(Authorization) 세 개념을 구분하지 못하는 것입니다. 이 세 가지는 밀접하게 연관되어 있지만 각각 별개의 관심사입니다.
아이덴티티는 시스템 내에서 사용자를 고유하게 식별하는 정보의 집합입니다. 이름, 이메일, 전화번호 같은 속성을 포함하며, 사용자가 "누구인지"를 정의합니다.
interface Identity {
id: string; // 고유 식별자
email: string; // 이메일
displayName: string; // 표시 이름
attributes: { // 추가 속성
department: string;
role: string;
mfaEnabled: boolean;
};
credentials: Credential[]; // 인증 수단 목록
}인증은 "주장된 아이덴티티가 진짜인지 검증하는 과정"입니다. 비밀번호, 생체 인식, 보안 키 등 다양한 팩터(Factor)를 사용하여 신원을 증명합니다.
인증 팩터는 세 가지 범주로 나뉩니다.
| 범주 | 설명 | 예시 |
|---|---|---|
| 지식(Knowledge) | 사용자가 아는 것 | 비밀번호, PIN, 보안 질문 |
| 소유(Possession) | 사용자가 가진 것 | 보안 키, OTP 기기, 스마트폰 |
| 존재(Inherence) | 사용자 자체 | 지문, 얼굴 인식, 홍채 |
다중 인증(MFA, Multi-Factor Authentication)은 서로 다른 범주의 팩터를 두 개 이상 조합하는 것입니다. 비밀번호(지식) + OTP(소유)가 대표적인 예입니다. 같은 범주의 팩터 두 개(비밀번호 + PIN)를 쓰는 것은 MFA가 아닙니다.
인가는 "인증된 사용자가 특정 리소스에 접근하거나 특정 작업을 수행할 권한이 있는지 결정하는 과정"입니다.
interface AuthorizationDecision {
subject: string; // 누가 (인증된 사용자)
action: string; // 무엇을 (읽기, 쓰기, 삭제)
resource: string; // 어디에 (문서, API 엔드포인트)
context: { // 어떤 상황에서
time: Date;
ipAddress: string;
deviceTrust: number;
};
decision: "allow" | "deny";
}
// 예시: "홍길동이 주문 #456을 수정할 수 있는가?"
const decision: AuthorizationDecision = {
subject: "user-123",
action: "update",
resource: "order:456",
context: {
time: new Date(),
ipAddress: "10.0.1.50",
deviceTrust: 0.95,
},
decision: "allow",
};세 개념의 관계를 흐름으로 표현하면 다음과 같습니다.
오늘날의 인증과 권한 관리 시스템은 과거에는 상상하지 못한 복잡한 도전에 직면해 있습니다.
마이크로서비스 아키텍처에서는 수십, 수백 개의 서비스가 독립적으로 동작합니다. 각 서비스가 인증을 개별적으로 처리하면 일관성이 깨지고, 중앙에서 처리하면 단일 장애점(SPOF)이 됩니다.
웹, 모바일, IoT, CLI 등 다양한 클라이언트에서 일관된 인증 경험을 제공해야 합니다. 각 플랫폼의 보안 모델과 제약이 다르기 때문에 단일 전략으로는 부족합니다.
2024년 Verizon DBIR 보고서에 따르면, 데이터 침해의 약 80%가 도난되거나 약한 자격 증명과 관련이 있습니다. 비밀번호 기반 인증은 피싱, 크리덴셜 스터핑(Credential Stuffing), 무차별 대입 공격에 지속적으로 노출됩니다.
GDPR(General Data Protection Regulation), PCI-DSS, SOC 2 등 각종 규제가 인증 시스템에 구체적인 요구사항을 부과합니다. 지역별로 다른 데이터 거주 요건까지 고려하면 설계 복잡성이 급격히 증가합니다.
단순한 역할 기반 접근 제어(RBAC, Role-Based Access Control)로는 현대 애플리케이션의 세밀한 권한 요구를 충족하기 어렵습니다. "이 문서의 작성자이거나, 해당 팀의 매니저이면서, 근무 시간 내에만 수정 가능"과 같은 조건은 RBAC만으로 표현하기 힘듭니다.
이러한 복잡한 권한 요구사항을 해결하기 위해 등장한 것이 관계 기반 접근 제어(ReBAC, Relationship-Based Access Control)입니다. Google의 Zanzibar 논문에서 시작된 이 모델은 5장에서 자세히 다룹니다.
이 시리즈는 총 10장으로 구성되어 있으며, 인증과 권한 관리의 이론적 기반부터 실전 구축까지 체계적으로 다룹니다.
| 장 | 주제 | 핵심 키워드 |
|---|---|---|
| 1장 | 인증과 권한 관리의 진화 | 역사, 개념 정리, 도전 과제 |
| 2장 | OAuth 2.1과 OIDC | 프로토콜, PKCE, DPoP |
| 3장 | Passkeys와 WebAuthn | 비밀번호 없는 인증, FIDO2 |
| 4장 | 아이덴티티 플랫폼 비교 | Keycloak, Auth0, Zitadel |
| 5장 | RBAC에서 ReBAC로 | Zanzibar, OpenFGA, SpiceDB |
| 6장 | 토큰 관리와 세션 전략 | JWT, 토큰 갱신, BFF 패턴 |
| 7장 | 제로 트러스트 아키텍처 | 지속적 검증, BeyondCorp |
| 8장 | API 인증과 서비스 간 통신 | mTLS, API 게이트웨이 |
| 9장 | 규제 대응과 컴플라이언스 | GDPR, PCI-DSS, NIST |
| 10장 | 실전 프로젝트 | 통합 구축, 모니터링 |
범위를 명확히 하기 위해, 이 시리즈에서 다루지 않는 주제도 짚어둡니다.
인증과 권한 관리는 소프트웨어 보안의 최전선입니다. 단순한 비밀번호 검증에서 시작하여, 세션, 토큰, 그리고 비밀번호 없는 미래까지 끊임없이 진화해 왔습니다. 이 진화의 방향을 이해하는 것은 단순히 역사적 호기심을 충족하는 것이 아니라, 올바른 보안 설계 결정을 내리기 위한 필수 전제입니다.
다음 장에서는 현대 인증의 기반이 되는 OAuth 2.1과 OIDC(OpenID Connect)를 깊이 있게 살펴봅니다. OAuth 2.0에서 무엇이 달라졌는지, PKCE가 왜 필수가 되었는지, 그리고 DPoP가 어떤 문제를 해결하는지 알아보겠습니다.
이 글이 도움이 되셨나요?
OAuth 2.1이 OAuth 2.0의 모범 사례를 어떻게 통합했는지, OIDC의 인증 레이어 구조, PKCE와 DPoP의 동작 원리를 코드와 다이어그램으로 설명합니다.
WebAuthn 프로토콜과 FIDO2 표준의 구조, 패스키의 등록 및 인증 플로우, 플랫폼 인증기와 크로스 디바이스 인증의 동작 원리를 설명합니다.
Keycloak, Auth0, Zitadel의 아키텍처와 기능을 비교하고, 셀프 호스팅과 SaaS 간의 트레이드오프, 렐름/테넌트 설계, 페더레이션 전략을 정리합니다.