78 lines
4.3 KiB
Markdown
78 lines
4.3 KiB
Markdown
---
|
|
title: error / sample-ticket-oauth2-resource-server-dependency-2026-05-27
|
|
source_type: error-note
|
|
status: raw
|
|
related_branches: [feature-skeleton-package-blueprint-contract]
|
|
related_projects: [ca-skeleton]
|
|
tags: [error, ca-skeleton, architecture, spring-boot, testing]
|
|
created: 2026-05-27
|
|
status_label: resolved
|
|
---
|
|
|
|
# error: sample-ticket-oauth2-resource-server-dependency-2026-05-27
|
|
|
|
> Layer: `raw/errors/` — 작업 중 마주친 단일 실패·트러블슈팅 기록. 원본은 raw에 영구 보관한다.
|
|
|
|
## Parent / 부모
|
|
|
|
- [[raw/branch-notes/feature-skeleton-package-blueprint-contract]] — reference code를 production module에서 `sample-ticket`으로 격리하는 중 sample module compile classpath가 부족했다.
|
|
- [[raw/project-notes/ca-skeleton-operational-contract]] — ca-tmpl sample fixture 격리 정책과 연결된다.
|
|
|
|
## 증상 / Symptom
|
|
|
|
- 에러 메시지 (원문 그대로):
|
|
```text
|
|
package org.springframework.security.oauth2.server.resource does not exist
|
|
cannot find symbol: class InvalidBearerTokenException
|
|
```
|
|
- 발생 컨텍스트: `cd src && ./gradlew test` 실행 중 `:sample-ticket:compileJava` 실패.
|
|
- 발생 시점: 2026-05-27
|
|
- 발생 환경: local ca-tmpl repository.
|
|
- 재현 가능 여부: `always` — sample-ticket 내부 `GlobalExceptionHandler`가 `InvalidBearerTokenException`을 import하지만 sample module에 resource-server starter가 없으면 재현.
|
|
|
|
## 재현 절차 / Reproduction
|
|
|
|
1. 기존 web error handler를 `sample-ticket` 내부 `adapter/web/error`로 이동한다.
|
|
2. `sample-ticket/build.gradle`에 web/security/validation/jpa starter만 둔다.
|
|
3. `cd src && ./gradlew test` 실행.
|
|
4. 기대 결과: sample-ticket이 production module과 별개로 자가 컴파일된다.
|
|
5. 실제 결과: OAuth2 resource-server 예외 type을 찾지 못해 compile 실패.
|
|
|
|
## 조사 단계 / Investigation log
|
|
|
|
- 2026-05-27 — full test 재실행 → `:sample-ticket:compileJava` 실패.
|
|
- 2026-05-27 — `GlobalExceptionHandler` import 확인 → `InvalidBearerTokenException`이 resource-server starter에서 제공되는 type임을 확인.
|
|
- 2026-05-27 — `sample-ticket/build.gradle`에 `spring-boot-starter-oauth2-resource-server` 추가.
|
|
- 2026-05-27 — full `./gradlew test` 재실행 → 성공.
|
|
|
|
## 근본 원인 / Root cause
|
|
|
|
- 직접 원인: `sample-ticket`의 compile classpath에 `spring-boot-starter-oauth2-resource-server`가 없었다.
|
|
- 근본 원인: 기존 production `adapter-web` module이 갖고 있던 external dependency를 sample module 이동 후에도 명시해야 했는데, project dependency만으로 external implementation dependency가 전파된다고 잘못 기대할 수 있었다.
|
|
- 트리거 조건: sample code를 별도 Gradle module로 격리하면서 compile dependency를 module-local로 재선언하지 않음.
|
|
|
|
## Sources / 근거
|
|
|
|
- [[raw/branch-notes/feature-skeleton-package-blueprint-contract]] — `sample-ticket`을 production과 분리된 fixture/sample consumer로 둔 결정.
|
|
- [[wiki/projects/ca-tmpl/clean-architecture-package-layout]] — sample-ticket 격리 적용 사실.
|
|
|
|
## 해결 / Resolution
|
|
|
|
- 적용한 조치: `sample-ticket/build.gradle`에 `org.springframework.boot:spring-boot-starter-oauth2-resource-server`를 추가했다.
|
|
- 검증 방법:
|
|
- `cd src && ./gradlew test` 성공.
|
|
- `cd src && ./gradlew verifyCleanArchitectureDependencies` 성공.
|
|
- 잔여 위험 / 후속 작업: sample-ticket이 production runtime classpath에 들어가지 않도록 Gradle dependency rule과 ArchUnit sample 역의존 금지를 계속 유지해야 한다.
|
|
|
|
## 회고 / Lessons
|
|
|
|
- 빨리 감지하는 신호: sample module로 이동한 Spring component가 기존 module의 external starter type을 import하면 sample module에도 명시 dependency가 필요하다.
|
|
- 예방 체크리스트 항목 후보: production code를 sample module로 격리할 때 project dependency와 external dependency를 분리해서 점검한다.
|
|
- wiki로 끌어올릴 가치가 있는 일반화된 교훈: sample/fixture module도 "실행되지 않는 코드"가 아니라 독립 compile 대상이므로 dependency contract가 필요하다.
|
|
|
|
## Related / 관련
|
|
|
|
- 트리거된 daily note: [[raw/daily-notes/2026-05-27]]
|
|
- 관련 branch note: [[raw/branch-notes/feature-skeleton-package-blueprint-contract]]
|
|
- 관련 wiki 개념: [[wiki/concepts/clean-architecture-package-layout]]
|