API Authorization (권한 판단, 정책 복잡성, 성능 균형)
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
API Authorization 전략은 권한 통제를 위한 필수 설계인가 시스템 복잡성을 증가시키는 부담인가
API Authorization 전략은 인증된 사용자가 어떤 자원에 접근할 수 있는지를 결정하는 과정입니다. Authentication이 “누구인가”를 확인하는 절차라면, Authorization은 “무엇을 할 수 있는가”를 정의하는 단계입니다.
보안의 핵심이라는 데는 이견이 없지만, 설계를 해보면 단순한 조건 체크 하나가 시스템 전체 구조를 흔드는 경험을 하게 됩니다. 직접 겪고 나서야 이게 선택의 문제가 아니라는 걸 깨달았습니다.
권한 판단은 어디서 시작되어야 하는가
API 요청이 들어오는 순간, 시스템은 이미 Authorization을 시작합니다. 사용자가 자원에 접근하려 할 때 그 요청이 허용 가능한지 판단하는 것, 이게 Authorization의 출발점입니다. Authentication(인증)이 "이 사람이 누구인가"를 확인하는 문이라면, Authorization(인가)은 "이 사람이 여기 들어올 수 있는가"를 묻는 자물쇠라고 보시면 됩니다.
처음 API 서버를 구성했을 때, 권한 검증 로직을 컨트롤러 레이어 곳곳에 흩뿌려 놨습니다. 그 결과 한 달도 안 돼서 중복 코드가 쌓이고, 특정 엔드포인트에서 검증이 누락되는 사고가 났습니다. 그때 처음으로 "권한 검증 로직의 위치"가 얼마나 중요한지 체감했습니다.
권한 검증을 API 레이어(미들웨어 수준)에서 처리할 것인지, 서비스 레이어 내부에서 처리할 것인지를 두고 팀 내에서도 의견이 갈렸습니다. API 레이어에서 일찍 차단하면 불필요한 연산을 줄일 수 있다는 주장도 있었고, 비즈니스 로직과 권한 판단을 묶어야 유연하다는 주장도 있었습니다. 저는 두 방법을 모두 써봤는데, 정답은 없고 서비스 규모와 팀 컨벤션에 따라 다르다는 쪽으로 결론이 기울었습니다. 중요한 건 일관성입니다. 어디서 검증하든 빠짐없이 적용되느냐가 보안의 핵심이었습니다.
요청 단계에서 권한 판단을 명확히 설계하지 않으면, 나중에 기능이 추가될 때마다 "이 API에도 권한 체크가 있나요?"라는 질문이 반복됩니다. 저는 그 질문을 수십 번 들은 뒤에야 미들웨어 수준의 공통 검증 레이어를 도입했고, 그 이후로 누락 사고는 확연히 줄었습니다.
정책 복잡성은 피할 수 없는가
권한 모델을 단순하게 유지해야 한다고들 합니다. 이 말에 동의하지만, 현실은 다릅니다. 시스템이 커질수록 단순한 RBAC(역할 기반 접근 제어, Role-Based Access Control)만으로는 한계가 옵니다. RBAC는 사용자에게 역할을 부여하고, 역할에 따라 접근 가능한 자원을 정의하는 방식인데, 역할의 종류가 늘어나면서 조합이 폭발적으로 증가하는 문제가 생깁니다.
그래서 등장하는 것이 ABAC(속성 기반 접근 제어, Attribute-Based Access Control)입니다. ABAC는 사용자 속성, 자원 속성, 요청 환경 등을 종합적으로 고려해서 권한을 판단하는 방식으로, RBAC보다 훨씬 정교한 정책 표현이 가능합니다. 예를 들어 "오전 9시~오후 6시 사이, 사내 IP에서 접속한 경우에만 특정 데이터에 접근 허용" 같은 복합 조건도 구현할 수 있습니다.
ABAC를 도입하면 유연성은 확실히 올라가는데, 정책 정의 자체가 코드가 아니라 별도의 정책 언어로 작성되다 보니 오히려 팀원 간 이해도 격차가 생겼습니다. 정책이 충돌할 때 어느 규칙을 우선 적용할지 기준을 잡는 것도 생각보다 시간이 많이 걸렸습니다.
이 경험을 통해 다음과 같은 순서로 접근하는 게 현실적이라고 생각합니다.
- 초기에는 RBAC로 단순하게 시작한다. 역할 3~5개 수준에서 충분히 커버되는 경우가 많습니다.
- 역할 조합이 10개를 넘어가거나 조건부 접근이 필요해지는 시점에 ABAC 도입을 검토합니다.
- 정책 정의는 코드와 분리하여 중앙 관리 도구(예: OPA, Open Policy Agent)를 활용합니다.
- 정책 충돌 우선순위 기준을 문서화하고, 팀 전체가 공유하는 컨벤션으로 유지합니다.
ABAC가 복잡성을 증가시킨다고 보는 시각도 있는데, 개인적으로는 복잡성 자체보다 "복잡성을 관리하는 체계가 없는 것"이 더 위험하다고 봅니다. 정책이 코드 곳곳에 하드코딩되어 있는 상태가 ABAC보다 훨씬 다루기 어려웠습니다.
성능 균형은 캐싱만으로 해결되지 않는다
Authorization은 모든 API 요청에서 실행됩니다. 초당 수백, 수천 건의 요청이 들어오는 서비스라면 권한 검증 로직 하나가 전체 응답 시간에 직접 영향을 줍니다. OWASP(오픈 웹 애플리케이션 보안 프로젝트, Open Web Application Security Project)의 API Security Top 10에서도 Broken Object Level Authorization이 매년 상위에 오를 만큼, 인가 처리는 보안과 성능 두 축을 동시에 챙겨야 하는 영역입니다.(출처: OWASP API Security Top 10 2023)
성능 문제를 해결하기 위해 권한 정보를 캐싱하는 방법을 많이 씁니다. 이건 꽤 효과적이나 함정이 있습니다. 캐시에 저장된 권한 정보가 실제 변경 사항을 즉시 반영하지 못하는 경우, 이미 삭제된 권한으로 접근이 허용되거나, 새로 부여된 권한이 뒤늦게 적용되는 문제가 생깁니다. 이 문제를 TTL(Time-To-Live, 캐시 유효 시간) 설정을 너무 길게 잡아서 겪었고, 수동으로 캐시를 날려줘야 하는 상황이 반복됐습니다.
권한 데이터의 일관성(Consistency)은 단순한 성능 이슈가 아니라 보안 이슈입니다. 권한이 변경되는 순간 모든 시스템에 동시에 반영되지 않으면, 그 사이에 잘못된 접근이 이루어질 수 있습니다. 분산 시스템에서는 이 문제가 특히 두드러지는데, 결국 캐시 무효화 전략과 권한 변경 이벤트 처리를 함께 설계해야 합니다.
일반적으로 캐싱만 잘 하면 성능 문제가 해결된다고 알려져 있지만, 캐싱은 시작점일 뿐입니다. 권한 검증 쿼리 자체를 최적화하고, 검증이 불필요한 경로는 명시적으로 제외하며, 권한 변경 시 캐시 무효화까지 자동화된 구조를 갖추는 것이 진짜 성능 균형입니다.
Authorization 설계를 두고 "과하다" vs "필수다"라는 논쟁은 계속됩니다. 저는 이 논쟁 자체가 서비스 규모를 고려하지 않아서 생긴다고 봅니다. 사용자 수십 명짜리 내부 도구에 ABAC를 도입하는 건 분명 과잉이지만, 다양한 역할과 수십만 사용자가 공존하는 서비스에서 RBAC만 고집하는 건 구조적 한계를 자초하는 것입니다. 지금 서비스에 맞는 모델을 선택하되, 나중에 확장할 수 있는 여지를 남겨두는 것이 Authorization 설계에서 가장 현실적인 기준이라고 생각합니다.
관련 글
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
댓글
댓글 쓰기