--- title: "Spring Security Concurrency Support — DelegatingSecurityContext* 클래스 공식 레퍼런스" source_type: official-doc url: https://docs.spring.io/spring-security/reference/features/integrations/concurrency.html archive_url: related_branches: [feature-background-job-async-contract] related_projects: [ca-skeleton] tags: [official-doc, ca-skeleton, security, spring-security, security-context-propagation] created: 2026-06-11 --- # Spring Security Concurrency Support — DelegatingSecurityContext* 클래스 공식 레퍼런스 > Layer: `raw/official-docs/` — Spring Security 공식 레퍼런스 원문 발췌·출처 기록. > 검증된 요약은 `/ingest` 후 `wiki/concepts/` 에 `source-summary-template` 형식으로 별도 작성. 원본은 raw 에 영구 보관. ## Parent / 활용 branch | Branch | 이 자료가 정당화하는 결정 | |---|---| | [[raw/branch-notes/feature-background-job-async-contract]] | D5 — SecurityContext 의 `@Async` 전파는 `DelegatingSecurityContextExecutor` / `DelegatingSecurityContextTaskExecutor` 를 통한 explicit opt-in 이 공식 메커니즘이라는 근거 (MODE_INHERITABLETHREADLOCAL 의 thread-pool 위험과 대비) | ## 출처 / Source - 원본 URL: https://docs.spring.io/spring-security/reference/features/integrations/concurrency.html - 아카이브 URL: (미작성) - 저자 / 조직: Spring Security team (VMware / Broadcom) - 발행일: 공식 레퍼런스 — 버전별 지속 갱신 - 마지막 확인일: 2026-06-11 ## 왜 저장했는지 / Why archived `feature-background-job-async-contract` 의 D5 결정("SecurityContext propagation = explicit opt-in only") 은 근거 없는 상태(`UNSUPPORTED_DECISION`) 였다. 본 공식 레퍼런스는 `DelegatingSecurityContextExecutor` 및 관련 클래스 목록을 통해 Spring Security 가 공식 권장하는 cross-thread SecurityContext 전파 메커니즘을 명시하므로, D5 의 외부 공식 근거로 보관한다. ## 핵심 인용 / Key quotes (verbatim, 5개) > [§Overview] "Spring Security stores security information on a per-thread basis, which means the `SecurityContext` is lost when work transfers to a new thread. Spring Security provides infrastructure to handle this in multi-threaded environments." > [§DelegatingSecurityContextRunnable] "The fundamental building block for concurrency support is `DelegatingSecurityContextRunnable`, which wraps a delegate `Runnable` to initialize the `SecurityContextHolder` with a specified `SecurityContext`." > [§DelegatingSecurityContextExecutor] "`DelegatingSecurityContextExecutor` accepts a delegate `Executor` instead of a `Runnable`, allowing code to remain unaware of Spring Security." > [§DelegatingSecurityContextExecutor / Using Current User] "Without a `SecurityContext` argument, the executor uses the currently logged-in user:" > [§Available Concurrency Classes] "These classes seamlessly propagate `SecurityContext` across threads while maintaining clean, security-agnostic application code." ## Claims Extracted / 추출된 주장 | Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove | |---|---|---|---|---|---| | SS-CONC-C1 | Spring Security 는 SecurityContext 를 per-thread 로 저장하므로, 작업이 새 스레드로 이전될 때 SecurityContext 가 손실된다 | [§Overview] "Spring Security stores security information on a per-thread basis, which means the `SecurityContext` is lost when work transfers to a new thread." | `official-vendor-doc` | `SecurityContextHolder` 기본 전략(`MODE_THREADLOCAL`) 사용 시 — 즉 대부분의 표준 Spring 애플리케이션 | `MODE_INHERITABLETHREADLOCAL` 이 설정된 경우의 동작 규칙, thread-pool 환경에서의 안전성 여부 | | SS-CONC-C2 | `DelegatingSecurityContextRunnable` 은 지정된 `SecurityContext` 로 `SecurityContextHolder` 를 초기화한 뒤 위임 `Runnable` 을 실행하고 완료 후 context 를 clear 하는 기본 빌딩 블록이다 | [§DelegatingSecurityContextRunnable] "The fundamental building block for concurrency support is `DelegatingSecurityContextRunnable`, which wraps a delegate `Runnable` to initialize the `SecurityContextHolder` with a specified `SecurityContext`." | `official-vendor-doc` | 단순 스레드 실행 단위(`Runnable`) 에서 SecurityContext 전파가 필요한 경우 | `Executor`/`ExecutorService`/`TaskScheduler` 수준 API 에 직접 사용하는 방법 (그것은 `DelegatingSecurityContextExecutor` 이하 클래스들) | | SS-CONC-C3 | `DelegatingSecurityContextExecutor` 는 `Executor` 를 래핑해 application code 가 Spring Security 를 인지하지 않아도 SecurityContext 전파가 투명하게 이루어지도록 하는 공식 메커니즘이다 | [§DelegatingSecurityContextExecutor] "`DelegatingSecurityContextExecutor` accepts a delegate `Executor` instead of a `Runnable`, allowing code to remain unaware of Spring Security." | `official-vendor-doc` | `java.util.concurrent.Executor` 구현체(예: `ThreadPoolTaskExecutor`)를 `DelegatingSecurityContextExecutor` 로 감쌀 때 | `DelegatingSecurityContextExecutor` 자체가 SecurityContext 를 *생성*한다는 의미가 아님 — caller 의 context 를 캡처하거나 명시적으로 주입해야 함 | | SS-CONC-C4 | `SecurityContext` 인수 없이 `DelegatingSecurityContextExecutor` 를 생성하면 executor 는 현재 로그인한 사용자(caller thread 의 SecurityContext) 를 사용한다 | [§DelegatingSecurityContextExecutor / Using Current User] "Without a `SecurityContext` argument, the executor uses the currently logged-in user:" | `official-vendor-doc` | caller thread 가 authenticated SecurityContext 를 가지고 있는 경우 | SecurityContext 가 없는 anonymous context 나 비동기 초기화 시점 context 의 정확성 | | SS-CONC-C5 | Spring Security 는 `DelegatingSecurityContextCallable`, `DelegatingSecurityContextExecutor`, `DelegatingSecurityContextExecutorService`, `DelegatingSecurityContextRunnable`, `DelegatingSecurityContextScheduledExecutorService`, `DelegatingSecurityContextSchedulingTaskExecutor`, `DelegatingSecurityContextAsyncTaskExecutor`, `DelegatingSecurityContextTaskExecutor`, `DelegatingSecurityContextTaskScheduler` 를 제공한다 | [§Available Concurrency Classes] "These classes seamlessly propagate `SecurityContext` across threads while maintaining clean, security-agnostic application code." | `official-vendor-doc` | Spring Security 가 classpath 에 있는 모든 Spring 애플리케이션 | `MODE_INHERITABLETHREADLOCAL` 대비 이 방식이 *더 안전하다*는 명시적 비교 진술 없음 — 안전성 비교는 별도 공식 문서 필요 | ## Usage Boundaries / 적용 경계 - 이 자료가 직접 증명하는 것: - `SS-CONC-C1`: per-thread SecurityContext 저장 정책 및 신규 스레드 전환 시 손실 사실 - `SS-CONC-C2`: `DelegatingSecurityContextRunnable` 의 역할(set → run → clear 패턴) - `SS-CONC-C3`: `DelegatingSecurityContextExecutor` 가 Spring Security 공식 cross-thread propagation 메커니즘임 - `SS-CONC-C4`: 인수 없는 생성자 → caller 의 현재 SecurityContext 사용 - `SS-CONC-C5`: 제공되는 Delegating* 클래스 목록 전체 - 이 자료가 증명하지 않는 것: - `MODE_INHERITABLETHREADLOCAL` 을 thread-pool 에서 사용하면 안 되는 이유 (그 위험은 이 문서에서 직접 언급되지 않음 — 별도 `SecurityContextHolder` 레퍼런스 필요) - `TaskDecorator` 패턴과 `DelegatingSecurityContextExecutor` 패턴의 trade-off 비교 - Spring Boot 의 기본 `ThreadPoolTaskExecutor` 설정이 `DelegatingSecurityContextTaskExecutor` 를 기본 사용한다는 사실 (이 문서 범위 밖) - 내 프로젝트에 적용하려면 추가 확인이 필요한 것: - ca-tmpl 의 `ThreadPoolTaskExecutor` 빈을 `DelegatingSecurityContextTaskExecutor` 로 감싸는 실제 설정 코드 검증 (`locally-verified` 등급 필요) - `TaskDecorator` 1개로 MDC + Observation + SecurityContext 를 모두 전파할 때 `DelegatingSecurityContextTaskExecutor` 와의 중복 여부 (`D5` 계약 구현 전 확인 필요) ## 메모 / Notes - 본 문서의 code sample 은 `SecurityContext` 를 직접 캡처해 전달하거나 인수 없는 생성자로 caller context 를 사용하는 두 패턴을 보여준다. `@Async` 메서드 사용 시에는 caller thread 가 HTTP request thread 가 아닐 수도 있으므로 opt-in 시 주의. - `DelegatingSecurityContextAsyncTaskExecutor` 는 Spring 의 `AsyncTaskExecutor` 구현체를 위한 전용 래퍼 — `@Async` + `TaskExecutor` 조합 시 가장 직접적인 대응 클래스. - 추가로 봐야 할 동일 출처 페이지: `https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html` (SecurityContextHolder storage strategy 상세), `https://docs.spring.io/spring-security/reference/reactive/configuration/webflux.html` (Reactor Context 기반 reactive 전파 — WebFlux 환경은 다른 메커니즘) ## Related / 관련 - 같은 주제 다른 official-doc: [[raw/official-docs/spring-transactional-event-listener]] (in-process event 전파 맥락) - 이 자료를 인용한 wiki 요약: (생성 시 추가)