Files
llm-wiki/raw/blog-topics/framework-free-method-authorization-clean-architecture-2026-06-08.md

4.8 KiB

title, source_type, status, related_branches, related_projects, tags, created, status_label, target_audience, inspiration_url, archive_url
title source_type status related_branches related_projects tags created status_label target_audience inspiration_url archive_url
blog-topic / Spring Security 없이 application layer 에 method-level 인가 걸기 blog-topic raw
feature-authentication-authorization-contract
ca-tmpl
blog-topic
ca-tmpl
security
authorization
clean-architecture
spring-security
method-security
2026-06-08 ready-for-canonical backend-engineer

blog-topic: framework-free method authorization in Clean Architecture

Layer: raw/blog-topics/ — 구현에서 나온 블로그 글감 seed. canonical 추출은 /ingest 시 별도.

Parent / 부모

글감 한 줄

"@PreAuthorize 를 쓰면 application layer 가 Spring Security 에 결합된다. annotation 은 core 에, 집행은 adapter 에 두면 layer 순수성을 지키면서 method-level 인가를 걸 수 있다."

핵심 논지 / Outline

  1. 문제: Clean Architecture 에서 application/domain 은 framework-free 여야 하는데, Spring method security(@PreAuthorize/@Secured)는 bean 을 org.springframework.security 에 결합시킨다.
  2. 분리: 결정(decision)메커니즘(mechanism) 분리.
    • core: @RequiresPermission(plain annotation) + AuthorizationPort(plain interface) + Permission(value object) + AuthorizationPrincipal(raw roles).
    • adapter: AuthorizationManager<MethodInvocation> 가 annotation 을 읽고 principal 을 매핑해 port 에 위임. @EnableMethodSecurity(prePostEnabled=false) + custom Advisor(ROLE_INFRASTRUCTURE) 로 wiring.
  3. 거부 → 403 의 2-hop: core 가 자체 예외 throw → adapter 가 Spring AccessDeniedException 으로 변환 → 에러 envelope.
  4. permission-centric RBAC: role=permission 묶음, registry 로 raw role→effective permission 해소(case-insensitive, fail-closed, no wildcard=least-privilege).
  5. 함정: CGLIB vs JDK proxy(concrete 주입 시 proxyTargetClass=true 필수), AOP self-invocation bypass, unauthenticated(AuthenticationException) vs unauthorized(AccessDeniedException) 구분. → raw/errors/method-security-cglib-vs-jdk-proxy-usecase-injection-2026-06-08
  6. 마이그레이션 path: port interface 덕분에 RBAC→ABAC 전환이 구현체 교체로 끝남.

차별점

대부분의 Spring 튜토리얼은 @PreAuthorize 를 service 에 바로 붙인다. 이 글은 "왜 그게 hexagonal/clean 구조에서 부채인가 + 어떻게 분리하나"를 코드(TransactionPort 선례와 동일 패턴)로 보여준다.

트리거 / Trigger

글감 / Topic seed

  • 한 문장 요지: application layer에 Spring Security annotation을 직접 붙이지 않고 plain annotation + port + adapter method-security로 method-level authorization을 구현한다.
  • 예상 제목 후보:
    • Clean Architecture에서 framework-free method authorization 만들기
    • @PreAuthorize 없이 application layer 인가 걸기

핵심 주장 후보 / Claim candidates

  • 사실 후보:
    • core annotation과 authorization port는 Spring Security type을 직접 의존하지 않는다.
    • adapter가 Spring AuthorizationManager와 advisor wiring을 소유한다.
  • 의견/해석 후보:
    • authorization decision과 framework mechanism을 분리하면 RBAC→ABAC migration path가 단순해진다.

Outline seed

  1. @PreAuthorize가 application layer purity를 깨는 경로를 설명한다.
  2. core annotation/port와 adapter enforcement를 분리한다.
  3. 403 envelope, CGLIB/JDK proxy, self-invocation bypass 한계를 적는다.

Canonical 전환 후보 / Canonical extraction candidates

  • wiki/projects/ca-tmpl/security-baseline-jwt-actuator-secrets.md 후보:
    • framework-free method authorization 글감.
  • 필요한 추가 검증:
    • 현재 @RequiresPermission, AuthorizationPort, method security adapter 구현 여부.

Sources / 근거 후보

미해결 / Unknown

  • 아직 확인해야 할 사실: method security custom advisor의 현재 구현·검증 여부.
  • 과장하면 안 되는 부분: Spring Security 자체를 부정하지 않고 ca-tmpl layer boundary 선택으로 제한한다.

Decision / 처리 결정

  • 액션: promote-to-canonical
  • 이유: wiki/projects/ca-tmpl/security-baseline-jwt-actuator-secrets.md 에 framework-free method authorization 글감으로 반영한다.
  • 다음 단계: blogify 전 구현 증거와 proxy/self-invocation 한계를 확인한다.