유비쿼터스 언어는 한 경계 안에서 현업(그 업무를 실제로 하는 사람들. 우리 서비스라면 산후 관리사 파견을 운영하는 분들) · 기획자 · 개발자 · 코드가 같은 것을 같은 말로 부르는 것이다. 식당으로 말하면 손님은 「곱빼기」, 홀 직원은 「대」, 주방장은 「2인분」, 주방 화이트보드는 「L사이즈」라고 부르는 상태를 없애는 것이다. 말을 옮길 때마다 뜻이 조금씩 새고, 손님이 「이거 시킨 거 아닌데요」라고 하면 넷이 모여 어디서 틀렸는지 다시 찾아야 한다. 에릭 에반스는 이것을 「번역은 소통을 무디게 한다」고 적었다(『Domain-Driven Design Reference』, 2015, 3쪽).
우리 표준에도 이 생각이 조금은 들어 있다. 패키지 구조 표준은 패키지를 carecontract(돌봄 계약)처럼 업무 단위로 나눈다. Repository 설계 표준은 메서드 이름을 findByStatusAndCreatedAtBefore(DB에 묻는 말)가 아니라 findExpiredPendingOrders(만료된 대기 주문 찾기, 일하는 사람의 말)로 지으라고 한다. 도메인 서비스 표준은 도메인 서비스 이름을 AccountTransfer처럼 하는 일 그대로 지으라고 한다. 그런데 찾아보니 이런 규칙은 패키지 · Repository 메서드 · 도메인 서비스 세 곳에만 있었다. 클래스 · 도메인 메서드 · 테이블 이름에는 아무 규칙이 없었고, 현업이 실제로 쓰는 말을 적어 둔 곳도 없었다.
이 글은 그 빈칸을 채운다. 정하는 것은 둘이다.
- 현업의 말을 코드 이름에 「그대로」 쓴다는 것이 무슨 뜻이고, 어디까지 거는가
- 현업 말과 코드 이름의 짝을 어디에 적어 두는가
먼저: 현업은 한국어로 말하고 코드는 영어로 짓는다
「현업의 말을 그대로 쓴다」에는 걸리는 것이 하나 있다. 우리 산후 관리사 파견 서비스(arimom)의 실제 코드를 보자(origin/dev, 2026-11-06 기준).
/**
* 계약에 붙은 관리사 한 차례. 돌봄 계약 애그리거트의 자식이다.
* ...
*/
public class CareContractAssignment { ... }
한 줄씩 따라가기. 「돌봄 계약」은 산모 한 명과 맺은 서비스 약속이고, 그 안에 「관리사 누구를 언제부터 보냈다」는 기록이 한 줄씩 쌓인다. 주석은 이 한 줄을 「차례」 라고 부르고, 클래스 이름은 Assignment(배정) 다. /** ... */는 클래스 위에 붙이는 설명 주석(Javadoc)이다.
말과 이름이 다른 것 자체가 잘못은 아니다. 현업은 한국어로 말하고 이름은 영어로 짓기 때문이다. 문제는 「차례가 곧 Assignment다」라는 약속이 어디에도 적혀 있지 않다는 것이다. 주석에서 우연히 두 말이 만났을 뿐이다. 그리고 「현업의 말을 그대로 쓴다」는 말도 여기서 손이 멈춘다. 한글 「차례」를 이름에 그대로 쓸지, 영어로 옮길지부터 정해야 하기 때문이다. 원칙 1은 그것을 정하고, 원칙 2는 옮긴 짝을 어디에 적을지 정한다.
원칙 1. 현업 말 하나에 영어 이름 하나를 정해 클래스 · 메서드 · 테이블에 똑같이 쓴다
정해야 했던 건 이거였다 — 「현업의 말을 그대로 쓴다」를 코드에서 무엇으로 지킬까.
안 A — 한글 그대로 이름에 쓴다
class 돌봄계약차례 { ... }
void 서명표시하기() { ... }
자바는 한글 이름을 허용해서 이 코드는 실제로 컴파일되고 돌아간다. 얻는 것은 분명하다. 현업 말과 코드 이름 사이에 번역이 아예 없다. 버린 이유는 코드가 두 언어로 섞이기 때문이다. 우리 코드는 Spring 같은 영어로 된 도구 위에서 돈다. 내가 짓는 이름만 한글이 되면 한 줄이 이런 모양이 된다.
돌봄계약차례 found = repository.findById(id).orElseThrow();
한 줄 안에서 한글과 영어가 번갈아 나와서 오히려 읽기 어렵다고 나는 판단했다. 재 본 것은 아니다. 테이블 이름도 걸린다. DB와 도구에 따라 한글 테이블 이름은 따옴표로 감싸야 하는 경우가 있고, 다른 도구로 옮길 때 깨질 수 있다. 이 부분은 직접 시험해 보지는 않았다.
안 B — 현업 말 하나에 영어 이름 하나를 정해 두고, 늘 그 이름만 쓴다
「차례 = Assignment」라고 한 번 정하면, 그 뒤로는 어디서든 Assignment만 쓴다. 식당으로 말하면 화이트보드는 영어로만 쓰되 「곱빼기 = Double」을 한 번 정해 두고 모두가 그것만 쓰는 것이다.
골랐다 — 안 B. 안 B에도 번역은 남는다. 현업과 이야기할 때 개발자는 여전히 Assignment를 「차례」로 옮겨 말한다. 다만 그 짝이 하나로 정해져 있어서, 사람마다 다른 단어로 옮기거나 곳마다 다른 이름이 생기지 않는다. 에반스가 「번역은 소통을 무디게 한다」고 한 것은 저마다 다른 말 사이를 그때그때 옮기는 상태다. 식당에서 넷이 각자 다르게 옮긴 것이 그것이다. 안 B는 번역을 없애지는 못하지만, 정해 둔 짝 하나로 줄인다. 그러면서 코드를 한 언어로 남긴다.
대신 「차례 = Assignment」라는 짝을 어딘가에 적어 둬야 한다. 적어 두지 않으면 영어 이름만 남고, 그게 현업의 무슨 말이었는지 아무도 모른다. 그 자리는 원칙 2에서 정한다.
같은 이름을 클래스 · 메서드 · 테이블에 걸고 계층 꼬리는 그대로 둔다
한 번 정한 영어 이름은 업무를 가리키는 자리마다 똑같이 쓴다. 클래스 이름, 그 업무를 다루는 메서드 이름(Repository 메서드도 포함한다), DB의 테이블과 그 안의 컬럼 이름이다. arimom 코드의 「차례」는 클래스 · 메서드 · 테이블이 이미 그렇게 되어 있다. 컬럼 이름은 확인하지 않았다.
클래스 CareContractAssignment ← Assignment 가 「차례」
CareContractAssignmentEntity ← Entity 는 계층 꼬리
메서드 contract.assign(...) ← 돌봄 계약(contract)에 차례를 붙인다
contract.withoutAssignment(...) ← 차례를 뗀다
테이블 TB_CARE_CONTRACT_ASSIGNMENT ← TB_ 는 테이블 접두어
한 줄씩 따라가기. 「차례」에 해당하는 영어 단어는 모두 Assignment(또는 동사 assign) 하나다. 테이블 이름은 DB 관례대로 대문자와 밑줄로 쓰지만 단어는 같다. 한 곳은 Assignment, 다른 곳은 Turn처럼 다른 단어면 안 된다. 그러면 같은 것을 두 이름으로 부르게 되고, 식당의 「대」와 「2인분」 문제가 코드 안에서 다시 생긴다. 「차례」를 글자대로 옮기면 Turn이 먼저 떠오르지만, 우리 코드는 「관리사를 배정한 한 줄」이라는 뜻을 담아 Assignment를 골랐다. 어느 단어로 정하든, 정한 뒤에는 하나만 쓴다는 것이 이 원칙이다.
Domain · Entity · Repository · Service · Snapshot 같은 꼬리와 테이블의 TB_ 접두어는 통일 대상이 아니다. 우리 코드는 한 업무를 화면을 받는 곳(api) · 일의 순서를 짜는 곳(application) · 업무 규칙이 있는 곳(domain) · DB와 이어지는 곳(infra)으로 나눠 패키지를 따로 두는데, 이 나눈 층 하나를 계층이라고 한다. Service · Snapshot(다른 업무에 내보내는 값 복사본)은 application, Domain은 domain, Entity는 infra에 있다는 표시이고, Repository는 DB에서 꺼내고 넣는 창구라는 표시다. 꼬리는 「이 클래스가 어느 계층에 있나」를 알려 주는 개발자의 표시라서, 현업은 이 말을 쓰지 않는다. 식당으로 말하면 메뉴 이름은 「곱빼기(Double)」로 통일하되, 「주문서 · 영수증 · 재료표」 같은 양식 이름은 주방 사람들 것이라 그대로 두는 것이다.
원칙 2. 현업 말과 영어 이름의 짝은 그 클래스의 Javadoc 첫 줄에 적는다
원칙 1의 대가를 치를 자리다. 정해야 했던 건 이거였다 — 「차례 = Assignment」라는 짝을 어디에 적어 둘까.
안 A — 따로 용어집 파일을 둔다
[GLOSSARY.md]
차례 = Assignment (돌봄 계약 안의 관리사 배정 한 줄)
서명 링크 = SigningLink
...
얻는 것은 현업 말 전체를 파일 하나에서 볼 수 있다는 것이다. 새로 온 사람이 한 번에 훑어보기 좋다.
버린 이유는 이름과 짝이 서로 다른 파일에 있게 되기 때문이다. 이름표를 물건에 붙이지 않고 공책에 따로 적어 두는 것과 같다. 어느 날 클래스 이름을 바꾸면, 바꾸는 사람이 여는 파일은 그 클래스 파일이다. 공책인 GLOSSARY.md는 열 일이 없다. 그래서 깜빡하기 쉽고, 깜빡하면 옛 이름이 그대로 남는다. 이 블로그 저장소도 같은 일을 겪었다. 표준 글 끝에 규칙 파일 내용을 손으로 옮겨 적어 두었는데, 2026-09-15에 세어 보니 50편 중 2편이 이미 실제 규칙 파일과 어긋나 있었다.
안 B — 그 업무를 나타내는 domain 패키지(업무 규칙이 있는 계층) 클래스의 Javadoc 첫 줄을 현업 말로 시작한다
/**
* 차례 — 계약에 붙은 관리사 한 줄. 돌봄 계약 애그리거트의 자식이다.
*/
public class CareContractAssignment { ... }
한 줄씩 따라가기. 첫 줄 맨 앞의 「차례」가 현업 말이고, 줄표(—) 뒤가 한 줄 뜻이다. 같은 Assignment가 CareContractAssignmentEntity에도 들어 있지만, 짝은 업무 규칙이 있는 domain 패키지의 CareContractAssignment 한 곳에만 적는다. Entity 같은 꼬리가 붙은 클래스는 그 업무를 다른 계층으로 옮겨 담은 것이라 거기에 또 적으면 두 벌이 된다.
얻는 것은 짝이 이름과 같은 파일, 바로 위 줄에 있다는 것이다. 이름표를 물건에 직접 붙인 것과 같다. 클래스 이름을 바꾸려고 이 파일을 열면 바로 위의 주석이 눈에 들어오고, 리뷰하는 사람도 같은 파일의 바뀐 줄들 사이에서 주석을 함께 본다. 실제 코드도 이미 비슷하게 하고 있어서(「계약에 붙은 관리사 한 차례」), 형식만 정해 모든 업무 클래스에 같은 자리를 주는 것이다.
골랐다 — 안 B. 솔직히 말하면 안 B의 주석도 컴파일과 테스트가 보지 않는다. 그 점에서는 안 A와 같다. 둘의 차이는 사람이 볼 기회다. 안 A는 이름을 바꾸는 사람이 열지 않는 파일에 짝이 있고, 안 B는 반드시 여는 파일의 바로 위 줄에 짝이 있다. 그래서 어긋남이 없어지지는 않아도 줄어든다. 기계로 잡을 수 있는 부분은 원칙 3에서 잡는다. 대신 현업 말 전체 목록을 보려면 주석을 모아 봐야 한다. 파일 하나를 여는 것보다 손이 더 간다. 이 대가는 원칙 3의 검사가 목록을 찍어 주는 것으로 조금씩 갚는다.
적는 말은 현업에게 확인한 말이다
안 B를 정하고 나서도 하나가 남는다. 「차례」가 정말 현업의 말인지는 코드만 봐서는 알 수 없다. 이 글을 쓰면서 나도 「현업은 이걸 뭐라고 부르나」라는 물음에 답하지 못했다. 주석의 「차례」도 개발자가 「이게 업무 말이겠지」 하고 쓴 것일 수 있다.
그래서 규칙은 「현업에게 확인한 말을 적는다」까지다. 확인하는 일 자체는 표준이 대신할 수 없는 사람의 일이다. 누구에게 어떻게 물을지는 정하지 않았고, 이 글에도 확인을 마친 본보기는 아직 없다. 위 예시의 「차례」도 확인하기 전의 말이라, 규칙대로라면 현업에게 물어본 뒤에 적어야 한다.
그리고 유비쿼터스 언어의 정의대로, 현업 말이 바뀌면 주석만 고치지 않고 영어 이름까지 바꾼다. 에반스는 「언어가 바뀌는 것은 모델이 바뀌는 것이다」라고 적고, 그러면 클래스 · 메서드 · 모듈 이름을 새 모델에 맞게 바꾸라고 했다(같은 책 4쪽). 주석만 고치면 현업 말과 영어 이름의 짝이 다시 어긋나기 때문이다.
원칙 3. 이름표가 붙었는지는 원본 파일을 읽는 테스트가 막고 말이 맞는지는 사람이 본다
원칙 2의 주석은 컴파일할 때 아무도 보지 않는다. 그대로 두면 「사람이 기억해야만 지켜지는 규칙」이 된다. 원칙 2에서 본 것처럼 이 블로그 저장소에서도 손으로 옮겨 적은 규칙이 조용히 낡은 적이 있다. 그래서 무엇을 기계에 맡기고 무엇을 사람에게 남길지부터 갈랐다.
| 확인할 것 | 누가 보나 | 왜 |
|---|---|---|
domain 패키지 클래스 위에 이름표(「현업 말 — 뜻」)가 붙었나 |
기계 | 파일을 열어 첫 줄 모양만 보면 된다 |
같은 것을 두 영어 단어로 부르나(Assignment와 Turn) |
사람(코드 리뷰) | 두 단어가 같은 뜻인지는 사람만 안다 |
| 이름표의 말이 정말 현업의 말인가 | 사람 | 현업에게 물어봐야 안다 |
코드 리뷰는 코드를 합치기 전에 다른 사람이 바뀐 코드를 읽어 보는 일이다. 상자로 말하면, 기계는 「모든 상자에 라벨이 붙었나」는 셀 수 있지만 「라벨에 맞는 물건이 들어 있나」는 사람이 열어 봐야 안다.
여기서 「기계」는 테스트를 말한다. 테스트는 「코드가 이래야 한다」를 확인하는 코드로, 빌드할 때마다 자동으로 돈다. 테스트 하나라도 실패하면 빌드가 실패한다. 우리는 빌드가 성공한 코드만 함께 쓰는 코드에 합치고 배포하므로, 실패한 코드는 거기서 멈춘다. 「테스트가 막는다」는 이 뜻이다.
첫 줄은 「말 — 」 모양까지 본다
정해야 했던 건 이거였다 — 기계가 첫 줄을 얼마나 깐깐하게 볼까. 여기서 「첫 줄」은 /** 바로 다음 줄, 곧 ` * 차례 — …의 *` 뒤 글자를 말한다.
arimom 코드(origin/dev, 2026-11-06)를 셌다. 대상은 domain 패키지의 public 클래스 · enum · record이고, 인터페이스(Repository 같은 것)는 뺐다. 179개였고, 그중 170개는 주석 첫 줄이 이미 한글로 시작했다. 하지만 「계약에 붙은 관리사 한 차례」처럼 거의 다 문장이었다. 「계약의 조건 — 기간·일수·…」처럼 「말 — 」 모양인 것은 4개뿐이었다. 어느 단어가 현업 말인지 정해져 있지 않은 것이다.
안 A — 첫 줄이 한글로 시작하는지만 본다. 지금 고칠 것은 9개뿐이다. 버린 이유는 이름표의 「말」을 꺼낼 수 없기 때문이다. 원칙 2가 정한 것은 「현업 말 — 뜻」이라는 짝인데, 첫 줄이 아무 한글 문장이어도 통과하면 그 짝을 확인하지 못한다.
안 B — 첫 줄이 「한글 말 — 」으로 시작하는지 본다. 줄표(—) 앞의 말을 기계가 꺼낼 수 있다. 「서명 링크」처럼 띄어쓰기가 있는 말도 된다. 대신 지금 있는 179개 중 175개가 걸린다.
골랐다 — 안 B. 안 A는 지금 당장 편하지만 규칙의 핵심인 짝을 보지 못한다. 안 B만 원칙 2가 정한 모양 그대로를 검사한다. 줄표 앞의 말을 꺼낼 수 있으니, 같은 테스트가 통과한 클래스마다 「현업 말 — 클래스 이름」을 실행 기록에 찍어 목록을 만들 수 있다.
대가인 「175개가 걸린다」는 봐주는 목록으로 다룬다. 테스트 폴더에 텍스트 파일을 하나 두고, 지금 걸리는 175개 클래스 이름을 한 줄에 하나씩 적는다. 이미 「말 — 」 모양인 4개는 적지 않는다. 테스트는 이 파일에 적힌 클래스를 건너뛴다. 새로 만드는 클래스부터 검사하고, 기존 클래스는 고칠 때 이름표를 붙이고 목록에서 지운다. 그래서 목록은 줄어들기만 해야 한다. 누가 새 클래스를 목록에 슬쩍 더해 검사를 피하면 목록이 늘어나는데, 그런 변경은 리뷰에서 본다.
이 대가에는 하나가 더 따라온다. 원칙 2의 대가로 남긴 「전체 목록을 보려면 주석을 모아 봐야 한다」는 바로 다 갚아지지 않는다. 봐주는 목록에 있는 175개는 아직 「말 — 」 이름표가 없으니 현업 말 목록에 찍히지 않는다. 처음 찍히는 것은 이미 「말 — 」 모양인 4개와 새 클래스뿐이고, 봐주는 목록이 줄어드는 만큼 현업 말 목록이 채워진다.
ArchUnit이 아니라 원본 .java 파일을 읽는다
정해야 했던 건 이거였다 — 이 검사를 어떤 도구로 할까.
안 A — 이미 쓰는 ArchUnit에 규칙을 더한다. arimom에는 구조를 검사하는 테스트가 이미 셋 있다(CrossDomainArchTest · LayerDependencyArchTest · PackagePrivateArchTest). 모두 ArchUnit이라는 도구를 쓴다. 얻는 것은 새 도구 없이 익숙한 방식 그대로 쓴다는 것이다.
버린 이유는 이 안으로는 아예 검사가 안 되기 때문이다. ArchUnit은 컴파일이 끝난 결과물인 바이트코드(.class 파일)를 들여다본다. 컴파일러는 프로그램이 도는 데 필요한 것만 .class에 옮기고, 사람이 읽으라고 단 주석은 버린다. 그래서 ArchUnit에는 이름표가 보이지 않는다. DTO 생성자 표준 원칙 7도 같은 이유로 「Lombok 표시는 소스에만 남고 바이트코드에 없어 ArchUnit이 볼 수 없다」고 적었다. 완성된 빵에는 레시피 카드가 붙어 있지 않은 것과 같다.
안 B — 원본 .java 파일을 글자로 읽는 테스트를 하나 둔다. 빵 대신 레시피 카드를 직접 읽는 것이다. 다른 테스트처럼 빌드할 때 함께 돌고, 구조를 지키는 테스트끼리 모아 두려고 기존 ArchUnit 테스트들과 같은 architecture 폴더에 둔다. domain 패키지의 .java 파일을 열어 클래스 위 주석 첫 줄이 「한글 말 — 」으로 시작하는지 보고, 봐주는 목록에 있는 클래스는 건너뛴다. 이름표가 없는 새 클래스가 생기면 빌드가 실패해서 그 자리에서 알 수 있다.
골랐다 — 안 B. 안 A는 주석을 볼 수 없어서 사실상 선택지가 하나뿐이었다. 대가는 그 테스트가 파일을 글자로만 읽는다는 것이다. ArchUnit은 「이건 클래스, 이건 메서드」를 알아서 가려 주지만, 글자로 읽으면 「어느 주석이 클래스 바로 위 주석인가」를 테스트 안에서 직접 찾아야 한다.
그래서 이렇게 한다 — 유비쿼터스 언어 표준의 규칙 파일
현업이 쓰는 말과 코드의 이름이 하나로 이어져야 한다. 말을 옮길 때마다 뜻이 샌다.
이름
- 현업 말 하나에 영어 이름 하나를 정한다. 한글 식별자를 쓰지 않는다.
- 한 번 정한 영어 이름은 클래스 · 메서드(Repository 메서드 포함) · 테이블 · 컬럼에 똑같이 쓴다. 같은 것을 곳마다 다른 영어 단어로 부르지 않는다.
- 계층을 나타내는 꼬리(
Domain·Entity·Repository·Service·Snapshot등)와 테이블 접두어(TB_)는 통일 대상이 아니다. 그대로 붙인다.
짝 적기
- 그 업무를 나타내는
domain패키지 클래스의 Javadoc 첫 줄을 현업 말로 시작한다. 예:/** 차례 — 계약에 붙은 관리사 한 줄. */ Entity등 계층 꼬리가 붙은 클래스에는 짝을 다시 적지 않는다.- 현업 말은 현업에게 확인한 말을 적는다.
- 별도 용어집 문서를 두지 않는다. 이름과 짝이 두 곳에 있으면 한쪽만 바뀌어 어긋난다.
- 현업 말이 바뀌면 Javadoc만 고치지 않는다. 영어 이름까지 바꾼다.
검사
domain패키지의 public 클래스 · enum · record(인터페이스 제외) Javadoc 첫 줄(/**다음 줄)이 「한글 말 — 」으로 시작하는지 테스트로 검사한다. 빌드에서 돈다.- 이 테스트는 원본
.java파일을 글자로 읽는다. 주석은 바이트코드에 남지 않아 ArchUnit이 볼 수 없다. - 테스트는 기존 ArchUnit 테스트와 같은
architecture테스트 패키지에 둔다. - 표준을 걸 때 이미 걸리는 클래스만 테스트 폴더의 봐주는 목록 파일(한 줄에 클래스 하나)에 넣고 새 클래스부터 검사한다. 기존 클래스를 고칠 때 이름표를 붙이고 목록에서 뺀다. 목록이 늘어나는 변경은 리뷰에서 본다.
- 같은 테스트가 「현업 말 — 클래스 이름」 목록을 출력한다.
- 같은 것을 두 영어 단어로 부르는지와 현업 말이 맞는지는 리뷰에서 본다.
판단 기준 정리
| 질문 | 답 | 결론 |
|---|---|---|
| 현업 말을 한글 그대로 이름에 쓰나? | 아니다 | 현업 말 하나에 영어 이름 하나를 정한다 |
| 그 영어 이름은 어디에 쓰나? | 업무를 가리키는 모든 자리 | 클래스 · 메서드(Repository 메서드 포함) · 테이블 · 컬럼에 똑같이 |
Entity · Repository · TB_ 같은 꼬리도 통일하나? |
아니다 | 계층 표시라 그대로 둔다 |
| 현업 말과 영어 이름의 짝은 어디에 적나? | 그 업무의 domain 패키지 클래스 |
Javadoc 첫 줄을 현업 말로 시작한다 |
| 용어집 파일을 따로 두나? | 아니다 | 이름과 짝이 두 곳이 되면 어긋난다 |
| 현업 말이 바뀌면? | 주석만으로는 안 된다 | 영어 이름까지 바꾼다 |
| 이름표가 붙었는지는 누가 보나? | 기계 | 원본 .java를 읽는 테스트. ArchUnit은 주석을 못 본다 |
| 첫 줄은 얼마나 깐깐하게 보나? | 「한글 말 — 」 모양까지 | 기존 175개는 봐주는 목록에 두고 새 클래스부터 |
| 같은 것을 두 단어로 부르는지, 현업 말이 맞는지는? | 사람 | 리뷰와 현업 확인 |
이 표준을 정하기까지
시작은 개념을 모른다는 것이었다. 「도메인 드리븐」이라는 이름을 붙인 우리 표준에 유비쿼터스 언어가 없다는 안건(#180, 2026-10-04)이 있었다. 그 이틀 전 40주차 주간 고찰에서 「현업도 무엇을 말해야 할지 몰랐다」가 나왔다. 현업의 이야기가 외주 기획자를 거쳐 개발자에게 오는 동안 업무의 예외 상황들이 빠졌고, 결국 개발자가 현업과 일주일 내내 직접 붙어 다시 알아냈던 일이다. 그 고찰의 결론은 「끌어내는 질문이 없었다」였지만, 말이 여러 사람을 거치며 새는 모양은 에반스의 「번역은 소통을 무디게 한다」와 닮아 있었다.
정의를 세우고 우리 쪽에 대 보니 앞부분만 있었다. 유비쿼터스 언어를 「같은 것을 같은 말로 부르는 것」으로 정리하고, 용어집과 다른 점을 「말이 바뀌면 코드 이름까지 바꾸느냐」로 갈랐다. 그러고 나서 표준 규칙을 찾아보니 「이름을 업무 말로 지어라」가 세 곳에만 있었다. 현업 말을 적어 둔 곳은 없었다.
「그대로」에서 처음 멈췄다. 「현업의 말을 이름까지 그대로 쓰나」를 묻자마자, 현업은 한국어로 말하고 코드는 영어로 짓는다는 사정이 걸렸다. 「그대로」는 「한글 그대로」일 수도 있고 「정해 둔 영어 이름 하나로」일 수도 있었다. 한글 그대로는 실제로 돌아가지만 코드가 두 언어로 섞여서 버렸다.
영어 이름을 고르자 짝을 적을 자리가 남았다. 버릴 수 없는 대가였다. 용어집 파일과 클래스 주석을 놓고, 이름과 짝이 두 곳에 있으면 어긋난다는 이유로 주석을 골랐다. 이름표를 물건에 붙이느냐, 공책에 따로 적느냐로 비유하니 갈림이 분명해졌다.
표준이 대신할 수 없는 일이 하나 남았다. 「차례」가 현업의 말인지 나도 답하지 못했다. 규칙은 「확인한 말을 적는다」까지만 두고, 확인은 사람의 일로 남겼다.
마지막으로 지키는 방법을 정하다가 숫자에 한 번 걸렸다(2026-11-08). 확인할 것을 기계 몫 하나와 사람 몫 둘로 나눈 뒤, 실제 코드를 세어 보니 domain 클래스 179개 중 170개가 이미 한글 첫 줄을 갖고 있었다. 느슨하게 보면 9개만 고치면 되는 상황이었다. 그래도 정한 모양(「말 — 」)을 그대로 검사하기로 했다. 느슨한 검사는 통과는 쉽지만 짝을 보지 못한다. 걸리는 175개는 봐주는 목록으로 미뤘다. 도구는 기존 ArchUnit 테스트에 붙이려다, 주석이 컴파일 결과에 남지 않는다는 것을 떠올리고 원본 파일을 읽는 쪽으로 바꿨다.
유비쿼터스 언어 표준에서 아직 정하지 않은 것
- 영어 단어를 무엇으로 고르나. 「차례」를
Turn이 아니라Assignment로 한 것처럼 뜻을 담는 단어를 고른다는 것까지만 봤다. 고르는 기준은 세우지 않았다 - 메서드에만 나오는 말의 짝은 어디에 적나. 짝은
domain클래스 주석에 적기로 했는데, 「서명 표시하기」처럼 클래스 없이 메서드에만 나오는 업무 말은 자리가 정해지지 않았다 - 현업에게 누가 어떻게 확인하나. 사람의 일로 남겼다
- 한 말이 두 도메인에서 다른 뜻일 때. 유비쿼터스 언어는 「한 경계 안에서」 통일하는 것이다. 그 경계(바운디드 컨텍스트)가 우리 패키지 구조와 같은지는 정하지 않았다
- 봐주는 목록을 언제 비우나. 기존 175개는 고칠 때 하나씩 뺀다고만 정했다. 한꺼번에 붙일지, 기한을 둘지는 정하지 않았다
- 현업에게 확인하기 전에 새 클래스를 만들어야 하면. 테스트를 통과하려면 이름표가 있어야 하는데, 확인 안 한 말을 적게 된다. 그때 어떻게 표시할지는 정하지 않았다
- 어떤 클래스를 검사에서 더 뺄까. 검사는
domain패키지의public클래스 · enum · record를 본다(인터페이스는 뺀다). 그 안의 예외 클래스처럼 현업 말이 없는 것을 더 뺄 기준과 줄표 글자 같은 세부 모양은 테스트를 만들면서 정한다(arimom 작업 ARIMOM-222)
정리
- 현업 말은 한글 그대로 쓰지 않고, 영어 이름 하나를 정해 그것만 쓴다. 번역은 남지만 짝이 하나라 사람마다 다르게 옮기지 않는다
- 그 이름은 클래스 · 메서드 · 테이블 · 컬럼에 똑같이 쓴다. 계층 꼬리(
Entity·Repository·TB_)는 그대로 둔다 - 짝은
domain패키지 업무 클래스의 Javadoc 첫 줄에 붙인다. 따로 용어집을 두면 이름을 바꾸는 사람이 열지 않는 곳에 짝이 남는다 - 적는 말은 현업에게 확인한 말이다. 말이 바뀌면 영어 이름까지 바꾼다
- 이름표가 붙었는지는 원본 파일을 읽는 테스트가 막는다. 주석은 컴파일 결과에 없어서 ArchUnit으로는 못 본다. 기존 클래스는 봐주는 목록에 두고, 같은 뜻 두 단어와 현업 말 확인은 사람이 본다
자신만의 철학을 만들어가는 중입니다.
댓글남기기