🔐 로그인에 성공했으니 관리자 페이지도 볼 수 있을까?
우리가 쇼핑몰에 로그인했다고 생각해봅시다. 아이디와 패스워드를 입력했고, 휴대폰으로 온 일회용 번호까지 맞게 입력했습니다. 이제 서버는 요청을 보낸 사람이 등록된 사용자라고 어느 정도 믿을 수 있습니다.
그렇다면 관리자 페이지에 들어가서, 다른 사용자의 주문을 취소해도 될까요?
당연히 안되겠죠? 로그인이라는 것은 제가 누구인지 확인했을 뿐, 제가 관리자라는 뜻은 아니기 때문입니다. 이 별거아닌 상황 안에 인증(Authentication)과 인가(Authorization)의 차이가 그대로 들어있습니다.
- 인증은 인증을 요청하는 사람이, 본인이라고 주장하는 신원과 실제로 같은지 확인하는 과정입니다.
- 인가는 인증된 사람이 이 리소스에 이 행동을 해도 되는가?를 판단하는 과정입니다.
앞에서 말한 인증이 온라인 시스템에서 이루어지는 경우를 디지털 인증이라고 합니다. NIST는 디지털 인증을 사용자가 비밀번호나 OTP처럼 자신의 계정에 연결된 인증 수단을 실제로 가지고 있고, 사용할 수 있다는 사실을 확인하는 과정이라고 설명합니다.1 반면 접근 제어는 인증된 사용자의 요청을 허용해도 되는지 판단하고, 그 결과에 따라 실제로 요청을 허용하거나 차단하는 과정입니다.2
둘은 대개 같이다니지만, 동일한 과정은 아닙니다. 먼저 인증을 통해 요청의 주체를 알아낸 뒤, 인가 정책으로 대상 리소스와 행동을 확인합니다. 인증에 성공했어도 권한이 없으면 요청은 거절되어야 합니다.
여기서 인가는 “허용할 것인가?”라는 결정의 문제입니다. 접근 제어는 그 결정을 정책으로 표현하고, 실제 시스템에서 허용하거나 거절하도록 강제하는 메커니즘까지 포함한다고 생각하면 편합니다. 뒤에서 살펴볼 ACL, RBAC, ABAC는 이 접근 제어 정책을 표현하는 서로 다른 방식입니다.
저 역시 처음에 “그럼 로그인한 사용자 정보에 관리자 여부만 저장하면 끝나는 것 아닌가?”라고 생각했습니다. 작은 서비스라면 실제로 그것만으로 충분할 수 있습니다. 그런데 사용자가 수만 명으로 늘고, 서버가 여러 개로 나뉘고, 회사 직원과 외부 애플리케이션까지 같은 리소스에 접근하기 시작하면 꽤 복잡해집니다.
🧱 기존 시스템에는 무엇을 막아야 했을까?
인증·인가가 없으면 서버는 네트워크로 들어온 요청이 누구의 요청인지 구분할 수 없습니다. URL만 알고 있는 사람이 다른 사용자의 개인정보를 읽거나, 아무 프로그램이나 결제 API를 호출하고, 일반 직원이 급여 파일을 수정할 수도 있습니다.
그렇다고 모든 요청을 막으면 서비스가 아무 일도 하지 못하겠죠. 기존 시스템이 풀어야 했던 문제는 결국 정상적인 주체에게 필요한 행동만 허용하고 나머지는 거절하는 것이었습니다.
여기서 정상적인 주체는 환경마다 달랐습니다.
- 웹 서비스에서는 브라우저 앞에 앉은 우리일 수 있습니다.
- 백엔드에서는 다른 서버나 배치 프로그램일 수 있습니다.
- 기업 내부에서는 특정 부서와 직무를 가진 직원일 수 있습니다.
사람들에게 패스워드를 입력하라고 할 수는 있지만, 새벽마다 실행되는 서버에 매번 패스워드를 입력해줄 수는 없습니다. 반대로 사람에게 서버용 개인키 파일을 나누어주고 평생 관리하라고 하는 것도 말이 안됩니다. 귀찮으므로.. 그래서 각 환경의 주체와 운영 방식에 맞는 기술이 등장했습니다.
🪁 사람이 웹 서비스에 들어올 때
1. 기억하는 것만 확인하는 패스워드
사람이 웹 서비스에 로그인할 때 가장 익숙한 수단은 당연히 패스워드입니다. 사용자가 알고 있는 비밀을 서버에 제시하고, 서버는 저장된 값과 비교합니다. 별도의 장비가 필요 없고 거의 모든 사용자가 입력할 수 있으니 사람과 서버가 처음 만나는 환경에 잘 맞았습니다.
하지만 패스워드에는 문제가 있습니다. 대개 사용자는 쉬운 문자열을 고르거나 여러 서비스에서 재사용하고, 공격자는 피싱이나 유출된 정보로 이를 탈취할 수 있습니다. 패스워드가 노출되면 공격자와 원래 사용자를 구분할 방법도 없습니다.
그래서 MFA(Multi-Factor Authentication, 다중 요소 인증)가 함께 사용됩니다. 알고 있는 패스워드에, 보안 키나 휴대폰, 또는 생체 정보처럼 서로 다른 종류의 인증 요소를 추가하는 방식입니다. NIST도 여러 인증 요소를 사용하는 MFA를 중요하게 다룹니다.3
패스워드와 MFA가 적합했던 이유는 확인하려는 대상이 사람이었기 때문입니다. 사용자는 로그인 순간에 비밀번호를 입력하고 추가 인증 요청에 반응할 수 있습니다. 인증이 끝나면 서버는 매 요청마다 패스워드를 다시 묻는 대신, 제한된 시간 동안 사용할 수 있는 세션을 발급합니다.
그런데 웹 서비스가 많아지면서 또 다른 불편함이 생깁니다. 각각의 서비스마다 패스워드를 따로 만들고 관리해야 할까요?
2. 로그인 결과를 전달하는 OIDC
우리가 자주 사용하는 Google로 로그인 같은 기능에서는 애플리케이션이 사용자의 Google 패스워드를 직접 받지 않습니다. Google과 같은 Identity Provider가 사용자를 인증하고, 애플리케이션은 그 인증 결과를 전달받습니다.
이때 사용하는 대표 기술이 OIDC(OpenID Connect)입니다. OIDC는 OAuth 2.0 위에 신원 계층을 추가해, 클라이언트가 인증 서버(위의 예시에서 Google)에서 인증한 사용자의 신원을 확인할 수 있도록 합니다.4 ID Token에는 누가 인증되었는지, 누가 토큰을 발급했는지, 어느 클라이언트를 위한 것인지 같은 Claim이 담깁니다.
여기서 OAuth 2.0과 OIDC를 같은 로그인 기술로 생각하기 쉬운데 목적이 다릅니다.
- OIDC의 핵심 질문은 “이 사용자는 누구인가?”입니다.
- OAuth 2.0의 핵심 질문은 “이 애플리케이션에 어느 범위의 접근을 맡길 것인가?”입니다.
🛰️ 서버가 다른 서버를 호출할 때
사용자가 주문 버튼을 누르면 주문 서버가 결제 서버와 재고 서버를 호출할 수 있습니다. 이때 결제 서버가 확인해야 하는 주체는 브라우저를 사용하는 사람만이 아닙니다. 지금 연결된 서버가 정말 주문 서버인가도 확인해야 합니다.
1. 간단한 호출자를 구분하는 API Key
API Key는 클라이언트에 발급한 비교적 단순한 비밀 문자열입니다. 서버는 요청에 포함된 Key를 보고 등록된 애플리케이션인지 확인하고, 사용량을 계산하거나 호출 한도를 적용하고, 필요하면 Key를 폐기합니다.
GET /weather/seoul HTTP/1.1Host: api.example.comX-API-Key: client-secret-value하지만 Key를 가진 프로그램은 대개 같은 존재로 취급됩니다. 누가 실제 사용자였는지, 이 요청만 따로 승인받았는지까지 표현하기는 어렵습니다. 복사된 Key는 다른 곳에서도 사용할 수 있으므로 저장, 전송, 교체와 폐기가 중요합니다. OWASP도 보호된 Endpoint의 요청마다 API Key를 확인하고, 클라이언트가 약속을 위반하거나 Key가 위험해지면 폐기할 수 있어야 한다고 권고합니다.5
API Key는 호출 애플리케이션을 식별하고 사용량을 제어하는 데는 편하지만, 중요한 사용자 인가 전체를 혼자 맡기기에는 정보가 부족합니다.
2. 공개키의 주인을 증명하는 Certificate
서비스 수가 많고 통신 상대를 더 강하게 확인해야 한다면 PKI(Public Key Infrastructure, 공개키 기반 구조)와 Certificate(인증서)를 사용할 수 있습니다.
인증서는 공개키와 이름 같은 주체의 신원정보를 묶고, 신뢰하는 인증 기관(Certificate Authority, CA)이 그 묶음에 서명한 문서라고 생각하면 편합니다. 서버는 CA의 서명을 검증해 “이 공개키가 우리가 신뢰하는 서비스의 것인가?”를 확인합니다.
그런데 인증서 파일만 제시한다고 인증이 끝나는 것은 아닙니다. 실제 통신에서는 인증서에 대응하는 개인키를 가지고 있음을 TLS 과정에서 증명하고, 상대는 인증서 체인과 신뢰 관계를 검증합니다. 인증서, 개인키 소유 증명, Protocol Handshake, 신뢰 검증이 함께 이루어져야 주체를 인증할 수 있는 것입니다.
일반적인 HTTPS에서는 사용자가 서버 인증서를 검증합니다. 서비스 간 통신에서는 양쪽이 서로 인증서를 확인하는 mTLS(Mutual TLS)를 사용해 클라이언트 서비스의 신원까지 검증할 수 있습니다. 패스워드를 사람이 입력할 필요가 없고, 개인키를 직접 보내지 않은 채 암호학적으로 소유를 증명할 수 있으니 자동화된 서비스와 Workload 인증에 잘 맞습니다.
물론 이 과정이 공짜는 아닙니다. 인증서를 발급하고, 만료 전에 갱신하고, 유출된 인증서를 폐기하며, 어떤 CA를 신뢰할지 관리해야 합니다. 서비스가 많을수록 이 운영 비용도 같이 커집니다.
🏢 회사 안에서 수많은 계정을 관리할 때
회사에 입사한 직원이 메일, 파일 서버, 인사 시스템, 프린터를 사용할 때마다 별도의 계정과 Password를 입력한다고 생각해봅시다. 퇴사자가 생기면 관리자는 모든 시스템을 찾아다니며 계정을 지워야 합니다. 하나라도 빠뜨리면 그대로 접근 통로가 남습니다. 귀찮은 정도가 아니라 그냥 위험합니다.
1. 사람 대신 역할에 권한을 붙이는 RBAC
직원이 10명이라면 각 사람에게 권한을 직접 붙일 수 있습니다. 직원이 10,000명이고 부서 이동이 계속된다면요? 한 명씩 파일과 API 권한을 고치는 순간 관리자는 사망(?)합니다.
RBAC(Role-Based Access Control, 역할 기반 접근 제어)는 사용자에게 권한을 바로 붙이는 대신 역할을 사이에 둡니다.
김개발 → 개발자 역할 → 배포 로그 읽기
박운영 → 운영자 역할 → 배포 실행, 배포 로그 읽기
이회계 → 회계 역할 → 정산 보고서 읽기
직원이 팀을 옮기면 수백 개의 리소스를 수정하는 대신 역할 할당을 바꿉니다. NIST는 조직에서 역할은 비교적 안정적이지만 사용자와 권한은 많고 자주 변하기 때문에, 역할을 통해 접근을 관리하면 운영과 검토가 단순해진다고 설명합니다.6
이 구조가 조직 내부에 적합했던 이유는 회사의 업무가 개발자, 운영자, 회계 담당자처럼 비교적 명확한 직무로 나뉘었기 때문입니다. 다만 현실의 모든 조건이 역할 하나로 끝나지는 않습니다. 운영자라도 퇴근 후 개인 기기에서 고객 데이터를 내려받는 요청까지 허용해야 할까요?
🌤️ 웹 API와 클라우드로 경계가 넓어질 때
1. Password를 넘기지 않고 권한을 맡기는 OAuth 2.0
사진 인화 애플리케이션이 사용자의 클라우드 사진 중 선택한 사진을 읽어야 한다고 가정해봅시다. 가장 단순한 방법은 그 애플리케이션에 클라우드 계정 패스워드를 알려주는 것입니다.
그런데 이 방식은 사진 앱이 메일, 문서, 계정 설정까지 건드릴 수 있는 자격증명을 가지게 만듭니다. 앱의 접근만 취소하고 싶어도 만약 접근을 못하게 하려면, 패스워드 자체를 바꿔야 하죠.
OAuth 2.0은 바로 이 문제를 해결하기 위한 인가 프레임워크입니다. 사용자는 Authorization Server에서 동의하고, 외부 애플리케이션은 패스워드 대신 제한된 Access Token을 받습니다. RFC 6749가 설명하듯이 목적은 제3자 애플리케이션이 사용자를 대신하거나 자기 자신을 대표해 HTTP 서비스에 제한된 접근 권한을 얻도록 하는 것입니다.7
예를 들어 Token의 Scope가 사진 읽기뿐이라면 그 Scope는 애플리케이션에 위임된 범위가 사진 읽기임을 나타냅니다. 다만 Scope만 보고 최종 권한이 자동으로 결정되는 것은 아닙니다. Resource Server가 Access Token과 Scope를 검증하고, 대상 사진과 사용자 관계 같은 자신의 접근 제어 정책까지 함께 적용한 뒤 실제 요청을 허용하거나 거절합니다. 유효 기간을 짧게 두거나 특정 애플리케이션의 Token만 폐기할 수도 있습니다. 그래서 OAuth는 사용자의 장기 자격증명을 공유하지 않고, 일부 권한만 위임해야 하는 웹과 API 환경에 적합했습니다.
IMPORTANTOAuth 2.0은 그 자체로 사용자 로그인 정보를 표준화한 인증 프로토콜이 아닙니다. OAuth로 받은 Access Token이 있다고 해서 애플리케이션이 임의로 “이 사용자는 누구다”라고 판단하면 안 됩니다. 로그인이 필요하다면 그 목적을 정의한 OIDC를 함께 사용해야 합니다.4
2. 리소스 가까이 붙는 ACL, 조직을 닮은 RBAC, 상황까지 보는 ABAC
웹 API와 클라우드에서는 한 사람이 여러 프로젝트에 참여하고, 서비스 계정과 Workload도 자원에 접근합니다. 리소스와 주체가 함께 늘어나면서 인가 방식도 한 가지만 사용하기 어려워졌습니다.
ACL(Access Control List, 접근 제어 목록)은 리소스에 “누가 어떤 행동을 할 수 있는지”를 직접 붙입니다. 개인 문서에 사용자 A는 읽기, 사용자 B는 읽기와 쓰기를 허용하는 방식입니다. 리소스별 공유 관계를 구체적으로 표현하기에는 직관적이지만, 사용자와 파일이 많아질수록 흩어진 목록을 검토하기 어렵습니다.
RBAC는 앞에서 본 것처럼 권한을 역할에 묶습니다. 클라우드 관리자, 읽기 전용 사용자, 배포 담당자 같은 반복되는 업무 권한을 관리하기 좋습니다. 하지만 “서울 지역의 개발 리소스에 업무 시간에만 접근하기!”처럼 역할 밖의 조건이 늘어나면 역할을 계속 새로 만들어야 합니다.
이때 ABAC(Attribute-Based Access Control, 속성 기반 접근 제어)는 사용자, 리소스, 요청 행동, 환경의 속성을 정책과 비교합니다. NIST SP 800-162는 ABAC를 주체와 객체, 요청된 작업, 경우에 따라 환경 조건의 속성을 정책과 비교해 요청을 허용하거나 거부하는 방식으로 정의합니다.8
허용 조건
주체.departmentABAC는 클라우드처럼 리소스가 동적으로 생기고 위치, 시간, 기기 상태 같은 조건이 중요한 환경에 잘 맞습니다. 대신 속성이 믿을 만하게 관리되어야 하고, 정책이 복잡해질수록 “왜 거절되었는가?”를 추적하는 비용이 생깁니다. 그래서 실제 시스템에서는 ACL, RBAC, ABAC 중 하나만 고집하기보다 리소스 공유에는 ACL, 직무 권한에는 RBAC, 세밀한 조건에는 ABAC를 함께 사용하기도 합니다.
🧭 결국 시스템은 무엇을 보고 결정했을까?
지금까지 등장한 기술을 하나의 요청으로 다시 모아보겠습니다. 기존 시스템의 인가 판단은 대체로 다음 질문으로 표현할 수 있습니다.
누가, 어떤 리소스에, 어떤 행동을, 어떤 조건에서 하려고 하는가?
인증 시스템은 패스워드, MFA, Ticket, Certificate, ID Token 등을 검증해 “누가”에 해당하는 신원을 만듭니다. 애플리케이션이나 API Gateway, 운영체제, 클라우드 IAM은 그 신원과 요청을 ACL, Role, Attribute, Scope 같은 정책에 대입합니다. 정책이 허용하면 실행하고, 아니면 거절합니다.
인증 정보 + 요청(Resource, Action) + 현재 Context ↓ 접근 제어 정책 평가 ↓ Allow 또는 Deny여기서 Principle of Least Privilege(최소 권한 원칙)가 기준이 됩니다. NIST는 이를 사용자나 프로세스가 맡은 작업을 수행하는 데 필요한 최소한의 권한만 허용하는 원칙으로 정의합니다.9
사진 읽기만 필요한 앱에는 사진 삭제 권한을 주지 않고, 로그만 조회하는 개발자에게 운영 서버의 종료 권한을 주지 않으며, 주문 서버가 결제 API를 호출할 때도 필요한 Endpoint와 행동만 허용하는 것입니다.
“나중에 필요할 수도 있으니 관리자 권한을 주자”가 훨씬 편해 보일 수 있습니다. 실제로 초기 설정은 편합니다. 하지만 자격증명이 탈취되거나 프로그램에 취약점이 생기면 공격자가 얻는 권한도 그대로 커집니다. 최소 권한은 사고가 절대로 발생하지 않게 만드는 원칙이 아니라, 사고가 발생했을 때 피해가 퍼질 수 있는 범위를 줄이는 원칙이라고 생각하면 편합니다.
🚪 다음 질문
기존 인증·인가는 사람이나 Workload처럼 비교적 명확하게 식별되는 주체가 사전에 정의된 Interface와 권한 범위 안에서 요청을 수행하는 환경을 중심으로 발전했습니다. 패스워드와 MFA는 사람을 확인했고, Certificate와 API Key는 서비스들을 구분했습니다. OAuth는 패스워드를 넘기지 않고 일부 접근을 위임했고, ACL·RBAC·ABAC는 확인된 주체의 요청을 정책과 비교했습니다.
중요한건, 기술은 달라도 마지막 판단은 같았다는겁니다. “누가 어떤 리소스에 어떤 행동을 할 수 있는가?”를 먼저 정의하고, 그 범위를 넘으면 거절하는 것입니다.
그렇다면 이제 이 질문이 남습니다.
AI Agent도 기존 시스템처럼 API를 호출하니 지금까지의 기술을 그대로 사용하면 될 것 같기도 합니다. 그런데 Agent는 사용자의 추상적인 의도를 받아 스스로 행동을 계획하고, 실행할 Tool을 선택하며, 하나의 목표를 위해 연속적인 요청을 생성합니다. 단순히 사람 대신 프로그램이 움직인다는 것만이 차이는 아닌 셈입니다.
그렇다면 이렇게 만들어진 각각의 요청이 정말 사용자의 의도와 권한 범위 안에 있는지, 기존의 인증·인가 모델만으로 충분히 판단할 수 있을까요?