toolchain을 Eclipse Temurin으로 고정한다

vendor를 적지 않으면 설치된 아무 JDK 21이나 잡히므로, 표준가이드가 정한
배포판(openjdk21u-jdk_x64_windows_hotspot_21.0.5)과 다른 것으로 조용히
빌드될 수 있다. SBOM의 JDK 항목도 그 전제 위에 있다.

폐쇄망에서는 toolchain 자동 다운로드가 동작하지 않으므로 빌드 머신에
Temurin이 미리 설치되어 있어야 한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 23:31:40 +09:00
parent 5c069a0ee7
commit 7afb4d9e05
5 changed files with 19 additions and 34 deletions

View File

@@ -72,9 +72,13 @@ tasks.named('check') {
group = 'io.shinhanlife.dap.biz.mcp'
version = '0.1.0'
// 표준가이드가 정한 배포판은 Eclipse Temurin(openjdk21u-jdk_..._hotspot_21.0.5)이다.
// 벤더를 적지 않으면 설치된 아무 JDK나 잡히므로, 가이드와 다른 배포판으로 조용히 빌드되는 것을 막는다.
// 폐쇄망에서는 toolchain 자동 다운로드가 동작하지 않으므로 빌드 머신에 Temurin이 미리 설치되어 있어야 한다.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
vendor = JvmVendorSpec.ADOPTIUM
}
}

View File

@@ -11,13 +11,13 @@
"group": "io.shinhanlife.dap.biz.mcp",
"name": "ax-hub-mcp-server",
"version": "0.1.0",
"description": "AX HUB MCP Server (Spring Boot 3.5.11 / Java 21)",
"description": "AXHUB MCP&Tool Service 공통 스택 (Java 21 / Spring Boot 3.5.11)",
"purl": "pkg:maven/io.shinhanlife.dap.biz.mcp/ax-hub-mcp-server@0.1.0"
},
"properties": [
{
"name": "axhub:scope",
"value": "MCP Java SDK 2.0.0과 그 런타임 전이 의존, 그리고 빌드 환경"
"value": "MCP Java SDK 2.0.0과 그 런타임 전이 의존, 그리고 빌드 환경. MCP Server와 Tool Service의 공통 스택에 적용된다"
},
{
"name": "axhub:source",
@@ -153,7 +153,7 @@
},
{
"name": "axhub:note",
"value": "문서 밖 $ref 조회는 ToolSchemaReferencePolicy가 차단(ADR-0011). joni·graal-js 미해석으로 pattern 검증이 java.util.regex(백트래킹)로 처리되어, ToolSchemaPatternPolicy가 반복 구조·수량자 개수·maxLength를 제한하고 patternProperties를 금지한다(ADR-0012). 둘 다 ToolMetadata 생성 시점 검사"
"value": "optional인 joni·graal-js를 해석하지 않아 pattern 검증에 JDK 정규식 엔진을 사용한다"
}
]
},

View File

@@ -1,15 +1,21 @@
# SBOM — AX HUB MCP Server
# SBOM — AXHUB MCP&Tool Service
- 산출물: `AXHUB_MCP_Server_SBOM_CycloneDX1.5.json` (CycloneDX 1.5 정본), `AXHUB_MCP_Server_SBOM_CycloneDX1.5.xlsx` (검토용)
- 대상: `ax-hub-mcp-server@0.1.0` (Java 21 / Spring Boot 3.5.11)
- 산출물: `AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.json` (CycloneDX 1.5 정본), `AXHUB_MCP_Tool_Service_SBOM_CycloneDX1.5.xlsx` (검토용)
- 대상: AXHUB MCP Server와 Tool Service의 공통 스택 (Java 21 / Spring Boot 3.5.11)
- 산출 기준 빌드: `ax-hub-mcp-server@0.1.0`
- 생성 기준일: 2026-08-18
## 대상 범위
MCP Server와 Tool Service는 같은 기술 스택과 같은 MCP SDK를 쓰므로 이 SBOM을 공통으로 적용한다.
`build.gradle`이 직접 선언한 오픈소스는 `io.modelcontextprotocol.sdk:mcp-json-jackson2:2.0.0`
하나이며, 이 SBOM은 그 **런타임 전이 의존 전체**와 **빌드 환경**을 담는다. Spring Boot starter
계열(web / validation / data-redis / actuator)은 glow f/w가 제공하는 플랫폼 구성이라 범위 밖이다.
다만 목록은 **MCP Server 빌드(`ax-hub-mcp-server@0.1.0`) 하나에서 산출했다.** Tool Service가 이
스택 밖의 의존(예: DB 드라이버, 연계 라이브러리)을 추가하면 그만큼은 이 SBOM에 없으므로, 해당
빌드에서 다시 산출해 합쳐야 한다.
| 구분 | 개수 | 내용 |
|---|---|---|
| 런타임 의존성 (scope: required) | 12 | 실행 산출물 classpath에 올라가는 라이브러리 |
@@ -20,45 +26,20 @@
공개 의무가 없다. JDK는 toolchain이 `languageVersion = 21`만 고정하고 벤더를 지정하지 않으므로,
실제 배포판이 정해지면 라이선스를 확정해 기재한다.
## 빌드 환경(scope: optional)과 제외 devDependencies의 차이
## 제외 항목
둘은 다르다. 혼동하지 않도록 구분해 둔다.
제외 항목과 사유는 엑셀 `Exclusions` 시트가 정본이다. 요약하면 다음과 같다.
- **빌드 환경 (scope: optional)** — BOM에 **수록한다**. JDK 21, Gradle 8.14.3처럼 빌드에 필요하지만
실행 산출물에는 들어가지 않는 것들이다.
- **제외 devDependencies** — BOM에 **수록하지 않는다**. Java에서는 `test` scope와
`annotationProcessor`가 여기 해당한다. 선언 4건이다.
- **test scope와 annotationProcessor** — 선언 4건. 산출물에 포함되지 않는다.
- `spring-boot-starter-test`, `com.squareup.okhttp3:mockwebserver:4.12.0`,
`org.junit.platform:junit-platform-launcher` (test scope)
- `org.springframework.boot:spring-boot-configuration-processor` (annotationProcessor)
나머지 제외 항목과 사유는 엑셀 `Exclusions` 시트에 있다. 핵심은 세 가지다.
- `joni`, `graal-js`, `graal-sdk` — json-schema-validator의 `optional`. ECMA262 정규식 검증을
쓰지 않아 해석되지 않으므로 약 50MB가 빠진다.
- `jakarta.servlet-api:6.1.0` — mcp-core의 `provided`. 산출물에 포함되지 않고 서블릿 컨테이너가 제공한다.
- `mcp:2.0.0`(aggregate), `mcp-json-jackson3:2.0.0` — Jackson 3 경로를 쓰지 않아 선언하지 않는다.
자세한 배경은 [mcp-java-sdk-adoption.md](../mcp-java-sdk-adoption.md) 참고.
## 적용된 보안 통제
`com.networknt:json-schema-validator`는 schema의 `$ref`가 문서 밖을 가리키면 그 주소로 직접 조회를
시도한다. `inputSchema`는 Tool Service 매니페스트에서 오므로, 통제가 없으면 매니페스트가 서버의
outbound 호출 대상을 정하게 된다.
`ToolSchemaReferencePolicy``ToolMetadata` 생성 시점에 문서 밖 `$ref`·`$dynamicRef`와 2020-12가 아닌
`$schema`를 거부한다. 근거와 검토한 대안은
[ADR-0011](../decisions/ADR-0011-tool-input-schema-stays-in-document.md)에 있다.
정규식도 같은 자리에서 막는다. optional인 `joni`·`graal-js`를 해석하지 않아 `pattern` 검증이 JDK 정규식
엔진으로 처리되고 백트래킹 폭증이 가능하므로, `ToolSchemaPatternPolicy`가 반복 구조와 수량자 개수, 정규식
길이를 제한하고 `pattern` 필드에 `maxLength`(≤256) 동반 선언을 요구한다. key 길이를 묶을 자리가 없는
`patternProperties`는 사용을 금지한다. 규칙은 JDK 21 실측에 근거하며 근거와 한계는
[ADR-0012](../decisions/ADR-0012-tool-input-schema-pattern-budget.md)에 있다.
남은 위험은 문자 집합이 겹치면서 무한 수량자가 3개 이하인 정규식이다. 이 조합은 통과하며 `maxLength`
256이면 수백 ms가 걸릴 수 있다. 두 통제는 위험을 없애지 않고 측정된 폭증 구간 밖으로 옮긴다.
## 산출 방법과 한계
버전과 해시는 `build.gradle` 선언에서 출발해 Gradle 로컬 캐시의 실제 `pom`을 따라가 그래프를