Skip to content

Repository files navigation

blog-lab

기술 블로그 글에서 주장한 동작을 독자가 직접 재현할 수 있게 만든 최소 예제 모음이다. 각 모듈은 verify.sh 하나를 실행하면 글이 주장한 결과가 그대로 나온다. 이 레포의 목적은 코드를 보여주는 게 아니라 주장을 검증 가능하게 만드는 것이므로, 의존성은 검증에 필요한 최소한만 두고 각 모듈은 다른 모듈에 의존하지 않는다.

모듈의 단위는 글이 아니라 주장 하나다. 보통은 글 한 편에 모듈 하나가 대응하지만, 한 글이 통제 조건이 다른 실험 두 개를 요구하면 모듈을 나눈다. 001과 002가 그런 경우다. 001은 컴파일러 플러그인만 남기려고 Hibernate를 일부러 뺐고, 002는 실제 기동을 봐야 해서 Hibernate가 필요하다. 한 모듈에 넣으면 둘 다 흐려진다.

목차

번호 주제 모듈 핵심 주장
001 Kotlin JPA 엔티티의 final @Entity는 지울 수 없다 001-jpa-entity-final @Entity는 no-arg 생성자를 합성하지만, final 해제는 Kotlin 2.3.20부터다
002 Java 엔티티의 XML 전용 매핑 @Entity는 지울 수 없다 002-java-entity-xml-only Java는 어노테이션 0개로도 orm.xml만으로 매핑된다 (001의 대조군)
003 metadata-complete의 한계 orm.xml로 옮길 수 있는 것과 없는 것 003-metadata-complete 어노테이션을 무시시킬 뿐, XML에 빠진 선언을 채워주지 않는다

실행

각 모듈 디렉터리에서 verify.sh를 실행한다.

cd 001-jpa-entity-final
./verify.sh

JDK 17 이상만 있으면 된다. Gradle은 wrapper가 받아온다.

전체 모듈 목록은 아래로도 볼 수 있다.

./gradlew modules

구조

blog-lab/
├── README.md                 # 이 파일. 전체 목차
├── settings.gradle.kts       # 모듈 등록 + Kotlin 버전 스위칭 지점
├── build.gradle.kts          # 공통 설정만
├── gradle.properties         # kotlinVersion (SSOT)
├── gradle/libs.versions.toml # 라이브러리 버전 카탈로그
└── NNN-slug/                 # 글 1편 = 모듈 1개
    ├── README.md             # 검증하는 주장 / 실행법 / 실제 출력
    ├── build.gradle.kts
    ├── verify.sh             # 이걸 실행하면 결론이 나온다
    └── src/

모듈 이름은 NNN-slug 형식이다. NNN은 추가 순서, slug는 검증하는 주장을 가리킨다. 글 URL과 같을 필요는 없다 — 한 글에 모듈이 여럿 붙기 때문이다.

새 모듈 추가

  1. NNN-slug/ 디렉터리를 만든다.
  2. settings.gradle.ktsinclude(...)에 한 줄 추가한다.
  3. 모듈 README.md검증하려는 주장을 먼저 한 문단으로 쓴다.
  4. verify.sh를 쓰고, 실제 실행 출력을 모듈 README에 붙인다.
  5. 위 목차 표에 행을 하나 추가한다. 모듈 링크는 상대경로(./NNN-slug)로 쓴다.

원칙

  • 각 모듈은 독립 실행 가능하다. 다른 모듈에 의존하지 않는다.
  • 의존성은 검증에 필요한 최소한만. 변수가 늘면 무엇이 원인인지 말할 수 없게 된다.
  • 코드보다 README가 중요하다. 뭘 왜 검증하는지가 명확해야 한다.
  • 실행 결과를 재현할 수 있는 게 이 레포의 전부다. 재현이 안 되면 그 모듈은 실패한 것이다.

이 레포와 AI

이 레포의 모듈과 스크립트는 AI 에이전트(Claude Code)로 작성했다. 그래서 층을 나눠 둘 필요가 있다.

누가 만들었나 무엇이 보증하나
검증할 주장 사람. 실무에서 겪은 것
관찰 장치 (verify.sh, 모듈 코드) AI 아무것도. 읽고 검토해야 한다
관찰 결과 (javap 출력, Hibernate 기동) JDK, Hibernate 도구 자체

가운데 줄만 의심하면 된다. "Kotlin 2.3.20부터 final이 풀린다"는 AI의 주장이 아니라 컴파일러가 만든 바이트코드이고, "어노테이션 0개로 매핑된다"는 Hibernate가 실제로 INSERT를 날렸다는 뜻이다. AI가 개입할 여지가 없는 층이다.

무너질 수 있는 지점은 하나다. 관찰 장치가 엉뚱한 것을 보고 있는 경우. 001의 verify.shjavap -v 출력에서 -m1을 쓰는 이유(뒤에 나오는 flags:는 필드/메서드 것이다)나, 002가 exclude-unlisted-classes로 클래스패스 스캔을 끄는 이유가 그래서 주석으로 남아 있다. 이 한 줄들이 빠지면 그럴듯하지만 틀린 결과가 나온다.

그래서 위 원칙 중 "의존성은 최소한만"과 "코드보다 README가 중요하다"가 여기서 안전장치 역할을 한다. 스크립트가 사람이 읽어서 검토할 수 있는 크기로 남아 있어야 이 구조가 성립한다. 모듈이 늘어나 검토되지 않은 스크립트가 섞이는 순간 이 문단은 거짓이 된다.

Kotlin 버전 스위칭

버전에 따라 동작이 달라지는 것을 보여주는 모듈이 있으므로, Kotlin 버전은 한 곳에서 갈아끼울 수 있게 해뒀다.

./gradlew build                          # gradle.properties의 kotlinVersion
./gradlew build -PkotlinVersion=2.2.20   # 오버라이드

값은 settings.gradle.ktspluginManagement가 읽는다. 플러그인 해석보다 먼저 평가돼야 하므로 버전 카탈로그가 아니라 gradle.properties에 둔다.

About

bluesocket.dev 블로그 재현 예제 모음

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages