docs(i18n): 파파고 분할 번역 요구사항과 검증 결과를 기록한다
This commit is contained in:
@@ -0,0 +1,154 @@
|
|||||||
|
# 파파고 번역 길이 분할 구현 계획
|
||||||
|
|
||||||
|
| 항목 | 내용 |
|
||||||
|
|---|---|
|
||||||
|
| 상태 | 구현·기능 범위 검증·리소스 정리 완료 |
|
||||||
|
| 요구사항 | [prd.md](prd.md), PC-001~005 |
|
||||||
|
| 현재 Phase | 1: 분할 호출과 완전한 결과 반환 |
|
||||||
|
| 활성 Goal | 없음 |
|
||||||
|
|
||||||
|
## 목표와 제약
|
||||||
|
|
||||||
|
긴 필드도 Papago 요청 길이를 넘지 않고 전체 번역 결과로 반환한다.
|
||||||
|
Kotlin 1.6.21, Java 17, Spring Boot 2.7.14와 기존 RestTemplate을 사용한다.
|
||||||
|
서비스 내부에 최소 분할 로직만 추가하며 인터페이스, 의존성, 언어 감지, AWS, DB, 워커는 변경하지 않는다.
|
||||||
|
작업 시작 시 트리는 깨끗했으며 기존 디렉터리에서 작업한다. 별도 worktree·배포·push는 하지 않는다.
|
||||||
|
사용자의 ULW Commit Discipline에 따라 검증 후 코드·테스트와 관련 문서를 각각 원자적으로 커밋한다.
|
||||||
|
|
||||||
|
### Phase 1: 분할 번역
|
||||||
|
|
||||||
|
- [x] **Task 1.1: 파파고 분할 호출 구현 (P1-T1)**
|
||||||
|
|
||||||
|
**Objective:** 요청당 5,000 이하, 입력 손실 없음, 결과 순서 유지, 부분 실패 시 성공 결과 없음.
|
||||||
|
**시작 조건:** PRD 확정 및 기존 테스트 확인.
|
||||||
|
**완료 증거:** RED/GREEN, focused 회귀, HTTP 표면 QA, 빌드, 변경 파일 정적 검사.
|
||||||
|
**범위 밖:** 문장 경계 최적화, AWS, 감지, 재시도 정책·공개 API 변경.
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `src/main/kotlin/kr/co/vividnext/sodalive/i18n/translation/PapagoTranslationService.kt`
|
||||||
|
- Create: `src/test/kotlin/kr/co/vividnext/sodalive/i18n/translation/PapagoTranslationServiceTest.kt`
|
||||||
|
- Verify: `src/test/kotlin/kr/co/vividnext/sodalive/i18n/translation/TranslationJobWorkerTest.kt`
|
||||||
|
- Verify: `src/test/kotlin/kr/co/vividnext/sodalive/i18n/translation/TranslationJobSchedulerTest.kt`
|
||||||
|
|
||||||
|
**Interfaces:** `TranslationProvider.translate(TranslateRequest): TranslateResult` 유지. 성공 시 원문별 결과 한 개,
|
||||||
|
조각 실패 시 빈 결과로 기존 워커의 실패 처리를 사용한다.
|
||||||
|
|
||||||
|
- [x] **RED:** 요청 길이 경계, 이모지 경계, 입력 순서, 중간 HTTP 실패·빈 응답 회귀 테스트 작성.
|
||||||
|
- [x] **RED 확인:** 새 focused test에서 미분할/부분 성공으로 인한 assertion 실패 확인.
|
||||||
|
- [x] **GREEN:** 최대 5,000 UTF-16 길이 및 서로게이트 보존 분할, 순차 호출·결합, 부분 결과 폐기.
|
||||||
|
- [x] **GREEN 확인:** 동일 focused test 통과.
|
||||||
|
- [x] **REFACTOR:** 이번 변경의 중복만 정리하고 직접 영향 테스트·빌드·정적 검사 수행.
|
||||||
|
|
||||||
|
**시나리오 계약:**
|
||||||
|
1. S1: 짧은 원문 및 5,000/5,001/10,001 길이에서 요청당 상한을 지키고 입력 전체와 결과 순서를 보존한다.
|
||||||
|
2. S2: 한글·경계 이모지·다중 입력에서 문자를 손상시키지 않고 결과 개수와 대응을 보존한다.
|
||||||
|
3. S3: 중간 HTTP 오류·빈 번역은 부분 성공이 되지 않으며 기존 무호출 가드는 유지된다.
|
||||||
|
|
||||||
|
**P1-T1 실행 증거:**
|
||||||
|
- RED (production 수정 전):
|
||||||
|
`./gradlew --no-daemon --offline test --tests 'kr.co.vividnext.sodalive.i18n.translation.PapagoTranslationServiceTest'`
|
||||||
|
→ exit 1, `17 tests completed, 11 failed`, XML `tests="17" failures="11" errors="0" skipped="0"`.
|
||||||
|
5,001/10,001자·한글·서로게이트·다중 원문의 미분할 JSON 요청이 assertion으로 실패했다.
|
||||||
|
짧은 원문의 HTTP 오류 뒤 `No further requests expected`로 불필요한 후속 호출을 재현했고,
|
||||||
|
본문 없는 응답에서는 빈 전체 결과 대신 앞선 번역과 빈 문자열을 반환했다. 가드·짧은 입력 6건은 통과했다.
|
||||||
|
- 구현: UTF-16 인덱스로 최대 5,000씩 자르되 high/low surrogate 사이의 경계는 한 단위 앞당긴다.
|
||||||
|
각 원문의 번역을 순차 누적해 한 결과로 반환하며, HTTP 오류·예외·null/blank 번역은 전체 빈 결과로 즉시 반환한다.
|
||||||
|
빈 원문 요소도 기존처럼 한 번 요청하도록 분할 helper의 `do/while`을 사용한다.
|
||||||
|
- GREEN:
|
||||||
|
`./gradlew --no-daemon --offline test --tests 'kr.co.vividnext.sodalive.i18n.translation.PapagoTranslationServiceTest'`
|
||||||
|
→ exit 0, `BUILD SUCCESSFUL in 1m 42s`, XML `tests="17" failures="0" errors="0" skipped="0"`.
|
||||||
|
모든 기대 JSON 요청을 순서대로 검증하고, 미등록 후속 요청은 assertion 실패로 처리하므로 실패 후 호출 중단도 검증했다.
|
||||||
|
- 변경 파일 정적 검사:
|
||||||
|
`./gradlew --no-daemon --offline -I "$run_dir/papago-lint.init.gradle" ktlintMainSourceSetCheck ktlintTestSourceSetCheck`
|
||||||
|
→ exit 0, `BUILD SUCCESSFUL in 2m 39s`. 소유 임시 init script에서 `ktlint.filter.include`를
|
||||||
|
`**/PapagoTranslationService.kt`, `**/PapagoTranslationServiceTest.kt`로 제한했다.
|
||||||
|
LSP는 이 구현 세션에도 제공되지 않아 실행하지 못했다. Kotlin production/test 컴파일과 파일 한정 ktlint로 보완했다.
|
||||||
|
- 회귀·빌드:
|
||||||
|
`./gradlew --no-daemon --offline test --tests 'kr.co.vividnext.sodalive.i18n.translation.*' bootJar`
|
||||||
|
→ exit 0, `BUILD SUCCESSFUL in 1m 38s`, `:bootJar`와 `:test` 모두 실행됐다.
|
||||||
|
XML 합계 28건 통과, 실패/오류/skip 0건: Papago 17, Worker 7, Scheduler 3, Normalizer 1.
|
||||||
|
`build/libs/sodalive-0.0.1-SNAPSHOT.jar` 생성을 확인했다. 범위 밖 리팩터링은 하지 않았다.
|
||||||
|
위임 범위인 구현·자동 검증으로 P1-T1을 완료하며, loopback HTTP 수동 QA와 독립 리뷰는 부모 세션의 P1-GATE에 남긴다.
|
||||||
|
|
||||||
|
**실행 명령:**
|
||||||
|
```bash
|
||||||
|
./gradlew test --tests 'kr.co.vividnext.sodalive.i18n.translation.PapagoTranslationServiceTest'
|
||||||
|
./gradlew test --tests 'kr.co.vividnext.sodalive.i18n.translation.*'
|
||||||
|
./gradlew bootJar
|
||||||
|
```
|
||||||
|
|
||||||
|
**수동 표면 검증:** 실제 서비스와 loopback HTTP 서버를 연결해 S1~S3의 요청 JSON·결과를 검증한다.
|
||||||
|
임시 driver 사용 시 작업 소유 디렉터리에만 두고 서버·파일을 종료/정리한다. 유료 외부 API는 호출하지 않는다.
|
||||||
|
|
||||||
|
- [x] **Phase Gate (P1-GATE): 리뷰·증거·정리**
|
||||||
|
|
||||||
|
**Objective:** 요구사항과 diff를 독립 리뷰하고 모든 실행 결과·미검증 범위를 기록한다.
|
||||||
|
**시작 조건:** P1-T1의 focused 검증 완료.
|
||||||
|
**완료 증거:** 리뷰의 차단 이슈 0개, 범위 외 변경 없음, 임시 리소스 정리 확인.
|
||||||
|
**TDD 예외:** 읽기 전용 리뷰와 정리이며 코드 변경이 아니다.
|
||||||
|
**대체 검증:** diff/파일 직접 확인과 테스트 결과 대조.
|
||||||
|
|
||||||
|
## 검증 기록
|
||||||
|
|
||||||
|
- 초기 상태: `git status --short` 출력 없음. 기존 Papago 전용 테스트는 검색에서 발견되지 않았다.
|
||||||
|
- 전체 테스트는 실행하지 않는다. 사용자 실행 명령: `./gradlew test`.
|
||||||
|
- LSP 도구는 현재 세션 도구 목록에 없어 실행할 수 없다. Kotlin 컴파일과 가능한 정적 검사로 보완하고 한계를 보고한다.
|
||||||
|
- 구현 실행 소유 디렉터리: `/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/papago-chunk.3apfr5/implement.j3Yd7s`.
|
||||||
|
첫 shell에서 `mktemp -d`로 생성했으며 모든 shell 명령은 `TMPDIR`, `NODE_COMPILE_CACHE`,
|
||||||
|
`BUN_RUNTIME_TRANSPILER_CACHE_PATH`를 이 디렉터리로 export한다. 공유 캐시·부모 디렉터리는 정리하지 않는다.
|
||||||
|
- 테스트는 서비스만 로드하는 `@SpringBootTest(classes = [PapagoTranslationService::class])`와
|
||||||
|
기존 `ReflectionTestUtils.setField(..., "restTemplate", ...)` seam을 사용한다.
|
||||||
|
`MockRestServiceServer`에서 실제 RestTemplate의 JSON·헤더·순서를 검증하므로 외부 Papago/AWS 요청은 없다.
|
||||||
|
별도 loopback HTTP 수동 QA와 독립 리뷰/P1-GATE 판정은 부모 세션이 수행한다.
|
||||||
|
- RED/GREEN/회귀/빌드 결과는 위 P1-T1 실행 증거에 기록했다. 전체 테스트와 실서비스 호출은 실행하지 않았다.
|
||||||
|
- GREEN 및 파일 한정 lint의 첫 실행은 각각 shell 도구의 120,000ms 제한으로 종료됐다.
|
||||||
|
테스트 실패나 컴파일 오류로 판정하지 않았으며, 제한을 600,000ms로 늘린 재실행에서 위 GREEN/정적 검사 성공을 확인했다.
|
||||||
|
기존 Gradle deprecation 경고(Gradle 9 비호환 안내)는 남아 있으며 이번 범위에서 수정하지 않는다.
|
||||||
|
- 리소스 정리 영수증: 모든 실행 명령 종료 후 `lsof +D "$run_dir"` 출력 없음으로 열린 파일이 없음을 확인했다.
|
||||||
|
소유 init script를 삭제하고 `rmdir "$run_dir" && test ! -e "$run_dir"`가 exit 0으로 끝났다.
|
||||||
|
최종 출력: `REMOVED owned directory: .../papago-chunk.3apfr5/implement.j3Yd7s; shared parent and caches untouched`.
|
||||||
|
공유 캐시·부모 디렉터리·다른 작업의 프로세스는 건드리지 않았다. 커밋·staging·push·worktree·subagent는 사용하지 않았다.
|
||||||
|
|
||||||
|
### P1-GATE 부모 세션 검증 — 2026-11-09
|
||||||
|
|
||||||
|
- 초기 부모 `./gradlew ktlintCheck`는 새 테스트의 import 순서로 exit 1이었다.
|
||||||
|
구현자가 `ReflectionTestUtils` import 순서를 바로잡았고 변경 파일 검사 성공을 확인했다.
|
||||||
|
- 부모 최종 `./gradlew --no-daemon --offline test --tests 'kr.co.vividnext.sodalive.i18n.translation.*' ktlintCheck bootJar`
|
||||||
|
→ exit 0, `BUILD SUCCESSFUL in 43s`, 19개 작업 UP-TO-DATE. 캐시 확인과 실제 재실행을 구분한다.
|
||||||
|
- 부모 fresh 실행 `./gradlew --no-daemon --offline test --rerun --tests 'kr.co.vividnext.sodalive.i18n.translation.*'`
|
||||||
|
→ exit 0, `BUILD SUCCESSFUL in 57s`, `:test` 실제 실행, 다른 9개 작업 UP-TO-DATE.
|
||||||
|
- 로컬 수동 QA: Java 17 임시 `PapagoChunkQa` driver에서 실제 `PapagoTranslationService`를 생성하고,
|
||||||
|
test-only reflection으로 endpoint를 `127.0.0.1` HTTP 서버로 바꾸었다. 가짜 인증 정보만 사용했다.
|
||||||
|
JSON 요청의 길이·원문 전체 복원·POST·언어·헤더와 결과 순서를 검사했다.
|
||||||
|
초기 기존 컴파일 결과는 5,001자에서 미분할로 실패했고, 수정된 컴파일 결과는 아래 9건 모두 통과했다.
|
||||||
|
|
||||||
|
| 시나리오 | 관측 요청 길이 (UTF-16) | 결과 |
|
||||||
|
|---|---|---|
|
||||||
|
| 짧은 원문 | 5 | PASS, 결과 1개 |
|
||||||
|
| 정확히 상한 | 5000 | PASS, 결과 1개 |
|
||||||
|
| 상한 초과 | 5000, 1 | PASS, 순서대로 결합 |
|
||||||
|
| 세 조각 | 5000, 5000, 1 | PASS, 순서대로 결합 |
|
||||||
|
| 한글 | 5000, 1 | PASS, 원문 복원 |
|
||||||
|
| 경계 이모지 | 4999, 3 | PASS, 서로게이트 보존 |
|
||||||
|
| 다중 입력 | 5000, 1, 4 | PASS, 원문별 결과 2개 |
|
||||||
|
| 중간 HTTP 500 | 5000, 5000 | PASS, 빈 전체 결과·후속 호출 없음 |
|
||||||
|
| 중간 빈 번역 | 5000, 5000 | PASS, 빈 전체 결과·후속 호출 없음 |
|
||||||
|
|
||||||
|
- driver 출력: `QA PASS: 9 scenarios; all loopback servers stopped; no external API calls`.
|
||||||
|
모든 서버를 `finally`에서 `stop(0)`으로 종료했고 driver 프로세스 exit 0을 확인했다.
|
||||||
|
- 독립 리뷰 1차: PC-001~005 정적 검토 통과, 기능·보안 차단 이슈 없음.
|
||||||
|
당시 미확인이던 import 정렬과 실행 결과는 위 부모 검증으로 보완했다. 최종 확인은 별도 기록한다.
|
||||||
|
- 미검증: 도구 미제공으로 LSP 실행 불가. 전체 테스트는 사용자 실행(`./gradlew test`).
|
||||||
|
실제 Papago 번역 품질·유료 API·운영 DB·이미 FAILED인 작업 재처리는 이번 범위가 아니다.
|
||||||
|
- 커밋 방침 정정: 초기 문서의 커밋 제외는 기본 정책 적용이었으나, 현재 사용자 ULW 지시에 명시된
|
||||||
|
검증 단위 커밋 요청을 반영한다. 구현 에이전트는 커밋하지 않았고 부모 세션이 검증 후 진행한다.
|
||||||
|
- fresh XML 확인: Papago 17, Normalizer 1, Scheduler 3, Worker 7, 합계 28건 모두 실패·오류·skip 0건.
|
||||||
|
- [독립 리뷰와 부모 검증 판정](reviews/phase-1-review.md): 기능·보안 차단 사항 없음.
|
||||||
|
리뷰 세션 재연결 도구 실패로 추가 독립 승인 응답은 받지 못했다. 최초 정적 리뷰와 부모 fresh 증거를 구분해 기록했다.
|
||||||
|
- 최종 리소스 영수증: 소유 Gradle daemon PID 99003의 TMPDIR가 작업 root와 일치함을 확인한 후 종료했다.
|
||||||
|
`ps -p 99003`은 프로세스가 없음을 확인했고 `lsof +D`는 열린 파일이 없었다.
|
||||||
|
소유 `papago-chunk.3apfr5` root(로컬 driver·class·추출 라이브러리 포함)를 제거하고 `test ! -e` exit 0을 확인했다.
|
||||||
|
출력: `CLEANUP PASS: owned run root removed; owned daemon absent; loopback servers stopped`.
|
||||||
|
노트의 필요한 근거는 이 문서에 옮겼고 임시 노트도 삭제한다. 공유 캐시·다른 프로세스는 유지했다.
|
||||||
|
- 코드·테스트 커밋: `b3c9b9bb`, `fix(i18n): 파파고 번역 요청을 길이 제한에 맞춰 분할한다`.
|
||||||
|
pre-commit hook의 변경 파일 ktlint와 커밋 메시지 사전·사후 검증을 통과했다. push는 하지 않는다.
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# 파파고 번역 요청 길이 분할 PRD
|
||||||
|
|
||||||
|
| 항목 | 내용 |
|
||||||
|
|---|---|
|
||||||
|
| 상태 | 구현·기능 범위 검증 완료 |
|
||||||
|
| 작성일 | 2026-11-09 |
|
||||||
|
| 범위 승인 | 사용자: 파파고 번역만 요청당 길이 제한에 맞춰 분할 호출 |
|
||||||
|
| 구현 계획 | [plan-task.md](plan-task.md) |
|
||||||
|
|
||||||
|
## 목적과 범위
|
||||||
|
|
||||||
|
현재 `PapagoTranslationService`는 각 필드를 한 번에 전송하여 5,000자를 넘으면 번역에 실패한다.
|
||||||
|
서비스 내부에서 긴 원문을 순서대로 분할 호출하고 결과를 하나로 합쳐 기존 호출자가 그대로 사용하게 한다.
|
||||||
|
AWS 추가, 언어 감지, DB 구조, 워커 재시도 정책, 공개 API, 새 의존성은 변경하지 않는다.
|
||||||
|
|
||||||
|
## 요구사항
|
||||||
|
|
||||||
|
| ID | 요구사항과 수용 기준 |
|
||||||
|
|---|---|
|
||||||
|
| PC-001 | 각 HTTP 요청의 `text`는 최대 5,000 UTF-16 코드 단위이다. 5,000 이하는 한 번, 5,001 이상은 여러 번 호출한다. |
|
||||||
|
| PC-002 | 분할은 원문 순서와 모든 문자를 보존하며 유효한 서로게이트 쌍을 끊지 않는다. 요청 텍스트를 결합하면 원문과 정확히 같다. |
|
||||||
|
| PC-003 | 각 입력 텍스트의 번역 조각을 순서대로 구분자 없이 결합하여 기존 `TranslateResult`의 텍스트별 대응을 유지한다. |
|
||||||
|
| PC-004 | 어느 조각이든 HTTP 오류 또는 빈 번역 결과이면 부분 번역을 성공 결과로 반환하지 않는다. 기존 워커가 실패로 판단할 빈 결과를 반환하고 이후 조각은 호출하지 않는다. |
|
||||||
|
| PC-005 | 빈 입력 목록, 동일 언어, 미지원 언어의 기존 무호출 동작 및 짧은 텍스트 호출 형식을 유지한다. |
|
||||||
|
|
||||||
|
## 기술 결정과 한계
|
||||||
|
|
||||||
|
- 공식 문서는 요청당 최대 5,000 characters를 명시하지만 Unicode 계산 방식은 명시하지 않는다.
|
||||||
|
구현은 보수적으로 UTF-16 길이를 제한하고 서로게이트 경계만 조정한다.
|
||||||
|
- 길이 기준 고정 분할을 사용한다. 문장 분석, 문맥 품질 보정, 조각 캐시, 병렬 호출은 이번 범위가 아니다.
|
||||||
|
- 모든 조각 성공 후에만 기존 전체 원문 기준 번역 캐시에 저장할 수 있도록 한다.
|
||||||
|
- 분할 시 HTTP 호출 수가 증가하며 중간 실패 후 기존 워커 재시도에서는 앞선 조각도 다시 호출될 수 있다.
|
||||||
|
- 원문과 자격증명을 오류 로그나 문서에 기록하지 않는다.
|
||||||
|
|
||||||
|
## 검증 기준
|
||||||
|
|
||||||
|
- 실제 서비스의 HTTP 요청 경계에서 5,000/5,001/10,001자, 한글, 이모지, 여러 입력, 중간 오류와 빈 응답을 검증한다.
|
||||||
|
- 기존 번역 워커·스케줄러 회귀 테스트와 `bootJar`를 실행한다. 전체 테스트는 저장소 정책대로 사용자 실행이다.
|
||||||
|
- 실제 유료 Papago 호출 대신 가짜 자격증명과 로컬 HTTP 서버를 사용하며 실서비스 번역 품질 검증과 구분한다.
|
||||||
|
|
||||||
|
## 근거
|
||||||
|
|
||||||
|
- [Papago Text Translation 요청 규격](https://api.ncloud-docs.com/docs/en/ai-naver-papagonmt-translation)
|
||||||
|
- [Papago 오류 코드](https://api.ncloud-docs.com/docs/en/ai-naver-papagonmt): `N2MT08`, `text parameter exceeds max length`.
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# 파파고 분할 번역 리뷰
|
||||||
|
|
||||||
|
## 리뷰 정보
|
||||||
|
|
||||||
|
| 항목 | 내용 |
|
||||||
|
|---|---|
|
||||||
|
| 대상 | P1-T1, 작업 트리의 서비스·테스트 변경 |
|
||||||
|
| 기준 | [PRD](../prd.md) PC-001~005, [계획](../plan-task.md) |
|
||||||
|
| 날짜 | 2026-11-09 |
|
||||||
|
| 리뷰어 | 독립 읽기 전용 에이전트, 실행 증거 확인은 부모 세션 |
|
||||||
|
| 상태 | 정적 리뷰 통과, 부모 세션 실행 검증 완료 |
|
||||||
|
|
||||||
|
## 범위와 판정
|
||||||
|
|
||||||
|
- `PapagoTranslationService.kt`: UTF-16 상한 5,000, 서로게이트 보존, 조각 순서와 원문 전체 보존을 확인했다.
|
||||||
|
- `PapagoTranslationServiceTest.kt`: 정확한 요청 JSON·헤더·순서, 5,000/5,001/10,001 경계,
|
||||||
|
한글·공백·이모지·다중 입력·HTTP 오류·빈 결과·기존 가드의 의미 있는 assertion을 확인했다.
|
||||||
|
- `TranslateRequest.kt`, `TranslationJobWorker.kt`: 기존 타입과 호출 계약을 유지하며 빈 결과는 저장 전에 실패 처리된다.
|
||||||
|
- HTTP 오류 또는 빈 조각이면 전체 빈 결과를 즉시 반환하여 앞선 입력·조각의 부분 결과가 성공으로 저장되지 않는다.
|
||||||
|
- 새 원문·인증정보 로그, 의존성, AWS·감지·DB·워커 변경은 없다.
|
||||||
|
|
||||||
|
**확정 기능·보안 차단 발견 사항 없음. 회귀 수정 Task 전환 항목 없음.**
|
||||||
|
|
||||||
|
## 실행 증거와 열린 항목 해소
|
||||||
|
|
||||||
|
| 검증 | 결과 |
|
||||||
|
|---|---|
|
||||||
|
| TDD RED | production 변경 전 17건 중 11건 assertion 실패, errors 0 |
|
||||||
|
| focused GREEN | 17건 통과 |
|
||||||
|
| 부모 fresh 번역 패키지 테스트 | `test --rerun --tests 'kr.co.vividnext.sodalive.i18n.translation.*'`, 28건 통과 |
|
||||||
|
| 로컬 HTTP QA | 실제 RestTemplate과 loopback 서버로 9개 시나리오 통과, 모든 서버 종료 |
|
||||||
|
| 정적 검사 | 초기 import 순서 오류 수정 후 변경 파일 ktlint 통과, 부모 최종 ktlintCheck 성공 |
|
||||||
|
| 빌드 | 구현 세션 bootJar 실제 생성, 부모 최종 bootJar UP-TO-DATE 성공 |
|
||||||
|
|
||||||
|
리뷰 당시 미확인이던 import 정렬과 실행 결과는 부모 세션이 최종 파일·XML·실행 출력으로 확인했다.
|
||||||
|
같은 리뷰 세션에 최종 증거를 전달하려 했으나 background continuation은 `Task not found`,
|
||||||
|
synchronous continuation은 inactivity timeout으로 응답하지 않았다. 이를 새 독립 승인으로 표기하지 않는다.
|
||||||
|
독립 정적 리뷰의 차단 사항은 없으며, 실행 증거 종결은 부모 세션 판정이다.
|
||||||
|
|
||||||
|
## 범위 밖과 한계
|
||||||
|
|
||||||
|
- 문장·문단 경계 최적화와 자동 구분자 삽입은 이번 요구 범위가 아니므로 고정 분할·무구분자 결합을 유지했다.
|
||||||
|
- 실제 유료 Papago 번역 품질과 운영 DB는 검증하지 않았다.
|
||||||
|
- LSP 도구 미제공으로 진단을 실행하지 못했다. Kotlin 컴파일과 ktlint로 보완했다.
|
||||||
|
- 전체 테스트는 저장소 정책에 따라 사용자 실행(`./gradlew test`)으로 남긴다.
|
||||||
Reference in New Issue
Block a user