권한 검증 위치

한 줄 정의

권한 검증 위치는 인증된 사용자가 특정 리소스에 접근 가능한지 확인하는 책임을 Controller, Service, Query, 공통 보안 계층 중 어디에 둘지 정하는 설계 문제다.

실무에서 왜 문제 되는가

  • 권한 검증이 여러 계층에 흩어지면 어떤 API가 안전한지 확인하기 어렵다.
  • Controller에서만 검증하면 내부 서비스 호출이나 배치 경로에서 누락될 수 있다.
  • Query 조건에 소유권을 넣지 않으면 조회 후 필터링 과정에서 데이터 노출 위험이 생긴다.
  • 공통 어노테이션만 사용하면 리소스 소유권처럼 데이터 기반 권한을 표현하기 어렵다.

동작 원리

  1. 요청의 인증 정보를 공통 필터나 인터셉터에서 확인한다.
  2. 기능 단위 권한은 Controller 또는 method security에서 빠르게 차단한다.
  3. 리소스 소유권과 상태 기반 권한은 Service에서 업무 규칙으로 검증한다.
  4. 목록 조회나 검색은 Query 조건에 접근 가능한 범위를 포함한다.
  5. 권한 실패는 일관된 예외와 로그로 처리한다.

실무 판단 기준

검증 대상적절한 위치이유
로그인 여부Filter, Interceptor대부분의 요청에 공통으로 적용된다
기능 roleController, method securityAPI 진입 지점에서 빠르게 차단한다
리소스 소유권Service업무 규칙과 함께 판단해야 한다
목록 조회 범위Query 조건권한 없는 데이터를 애초에 조회하지 않는다
관리자 예외 정책Servicerole과 리소스 상태를 함께 판단한다

자주 나는 실수

  • @PreAuthorize("isAuthenticated()")만 붙이고 소유권 검증을 끝냈다고 생각한다.
  • 목록 API에서 전체 데이터를 조회한 뒤 애플리케이션에서 필터링한다.
  • Service 내부 메서드가 다른 진입점에서도 호출된다는 점을 고려하지 않는다.
  • 관리자 role이면 모든 리소스 접근을 허용한다.
  • 권한 실패 로그에 민감한 요청 값을 그대로 남긴다.

확인 방법

  • 테스트: 소유자가 아닌 사용자가 단건 조회, 목록 조회, 수정, 삭제를 모두 실패하는지 확인한다.
  • 테스트: 관리자 예외가 필요한 기능과 필요 없는 기능을 분리해 검증한다.
  • 코드 리뷰: 권한 조건이 Controller, Service, Query 중 어디에서 보장되는지 추적한다.
  • 로그: 권한 실패 시 사용자 id, 리소스 id, 정책 이름, trace id를 남긴다.

장점과 한계

방식장점한계
공통 필터로그인 여부를 일관되게 확인한다리소스별 권한은 알기 어렵다
Controller 검증API 진입점에서 의도가 보인다내부 호출이나 재사용 경로에서 누락될 수 있다
Service 검증업무 규칙과 함께 판단할 수 있다반복 코드가 생길 수 있다
Query 조건권한 없는 데이터 조회 자체를 줄인다조건이 복잡해지면 테스트가 중요하다

짧은 예제

public List<OrderSummary> findMyOrders(AuthenticatedUser user, OrderSearchCondition condition) {
    return orderQueryRepository.findSummaries(
        condition.withOwnerId(user.id())
    );
}

목록 조회는 조회 후 필터링보다 query 조건에 접근 가능한 범위를 포함하는 방식이 안전하다.

핵심 요약

권한 검증은 한 계층만의 문제가 아니라 요청 진입, 업무 규칙, 조회 조건에 걸친 설계 문제다.

로그인 여부는 공통 계층에서 처리할 수 있지만 리소스 소유권은 업무 규칙과 함께 봐야 한다.

목록 조회는 권한 없는 데이터를 가져온 뒤 제거하는 방식보다 query 조건에 권한 범위를 포함하는 것이 안전하다.

Controller 검증은 의도를 드러내지만 내부 호출 경로까지 보장하지 못할 수 있다.

Service 검증은 반복될 수 있으므로 정책 메서드나 도메인 규칙으로 정리할 수 있다.

권한 실패는 403으로 처리하고 감사 가능한 최소 정보만 로그에 남긴다.

꼬리 질문

  • 권한 검증은 Controller와 Service 중 어디에 두는 것이 좋은가?
  • 목록 조회에서 권한 검증을 어떻게 보장할 것인가?
  • 공통 보안 어노테이션으로 해결하기 어려운 권한은 무엇인가?

관련 문서