Jinx
TL;DR
JPA Entity 변경을 컴파일 타임에 감지하여 MySQL DDL SQL을 자동 생성하는 오픈소스 라이브러리. APT의 처리 순서 비보장·증분 컴파일 문제를 지연 처리 큐와 JSON 스냅샷으로 해결하고, rename 휴리스틱의 위험성을 인식하여 완전한 Deterministic Diff로 전환했습니다.
📊 핵심 아키텍처
문제 정의 & 해결 과정
📝 Jinx 개발 회고
JPA 애노테이션으로 DB 마이그레이션을 자동화하는 과정에서 겪은 문제와 해결 과정
개요
JPA를 사용하는 프로젝트에서 Entity 변경 시 수동으로 마이그레이션 파일을 작성하는 번거로움을 해결하기 위해 개발한 도구입니다. Java Annotation Processor를 활용하여 컴파일 타임에 Entity를 분석하고, 스키마 변경사항을 자동으로 감지하여 MySQL DDL과 롤백 SQL을 생성합니다. 현재 MySQL을 대응하고 있습니다. 개발 과정에서 APT의 처리 순서 비보장 문제는 지연 처리 큐(deferredEntities)와 동적 재시도 횟수로, 증분 컴파일 환경에서의 불완전한 Entity 노출 문제는 JSON 스냅샷 비교 방식으로 해결했습니다. 또한 rename 탐지 휴리스틱이 데이터베이스 연구 분야에서 20년 이상 다뤄진 '스키마 매칭' 난제임을 파악하고, 운영 DB 안전성을 최우선으로 삼아 과감히 제거하여 완전한 Deterministic Diff로 전환했습니다.
핵심 성과
- ✓Java Annotation Processor를 활용한 컴파일 타임 Entity 분석
- ✓APT 처리 순서 비보장 문제를 지연 처리 큐(deferredEntities)와 동적 재시도 횟수(max(20, entityCount×2))로 해결
- ✓증분 컴파일 환경에서 불완전한 Entity 노출 문제를 JSON 스냅샷 기반 비교 전략으로 극복
- ✓rename 탐지 휴리스틱이 '스키마 매칭' 연구 난제임을 인식, 운영 안전성을 위해 Deterministic Diff로 전환
- ✓테이블, 컬럼, FK, 인덱스 등 모든 스키마 변경사항 자동 감지 및 MySQL DDL·롤백 SQL 생성
- ✓멀티 모듈 구조로 설계하여 Maven Central에 정식 배포 (v0.1.2)
회고
처음엔 간단해 보였는데, 갈수록 APT라는 환경의 특수성과 DB 마이그레이션이라는 분야의 복잡성이 드러났다. rename 탐지를 제거하기로 한 결정이 기술적으로 가장 어려웠지만, 가장 올바른 선택이었다고 생각한다.
- —APT는 런타임과 완전히 다른 환경이다. Class.forName()이 안 되고, TypeElement의 라운드 유효성을 관리해야 하는 등 처음엔 당황스러운 제약이 많았다. 하지만 그 제약들이 생긴 이유를 이해하면서 컴파일러 동작 방식을 더 깊이 배웠다.
- —rename 탐지가 '스키마 매칭'이라는 20년 된 연구 분야의 문제임을 뒤늦게 알았다. 코딩을 시작하기 전에 해당 도메인 공부가 먼저였어야 했다. 기술보다 도메인 이해가 먼저라는 교훈을 얻었다.
- —'똑똑한 자동화'가 DB처럼 중요한 시스템에서는 오히려 위험할 수 있다. Deterministic한 결과를 내는 단순한 도구가 더 신뢰할 수 있다는 걸 배웠고, 이를 실제 결정에 반영했다.
- —Maven Central 배포는 생각보다 진입장벽이 높았다. 멀티 모듈 구조 설계와 배포 파이프라인 구성이 기능 구현만큼이나 중요한 작업이었고, 라이브러리를 만드는 것과 배포 가능한 라이브러리를 만드는 것은 다르다는 걸 체감했다.