Search
🔵

Mapper의 방향에 따라 책임이 다르다. Mapper의 위치를 방향에 따라 고민해서 결정하라.

Contract는 안쪽이 바깥으로 무엇을 노출할지를 정한 공개 표면이다. 따라서 헥사곤 내부의 contract는 producer의 책임으로 이해하는 것이 자연스럽다. 반대로 Contract를 받아 consumer가 자기 DTO나 Command, 혹은 자기 컨텍스트의 해석 가능한 타입으로 바꾸는 일은 consumer의 책임이다. 이 변환은 단순 복원이 아니라, 외부 표면을 이 컨텍스트가 어떤 의미로 읽을 것인지 결정하는 해석이기 때문이다.
반면 ORM은 공개 표면이 아니라 persistence 계층의 기술 세부사항이다. 그래서 도메인/애플리케이션 계층의 타입 → ORM과 ORM → 도메인/애플리케이션 계층의 타입가 둘 다 같은 adapter 안에 있어도 자연스럽다. ORM은 시스템 바깥과의 약속이 아니라 특정 저장소 구현의 내부 표현이기 때문이다. 이 경우 Mapper는 경계의 양쪽에 흩어지는 것이 아니라, persistence 계층 내부에 응집되는 편이 맞다.
Mapper는 단순한 객체 복사 유틸리티가 아니라, 경계의 책임을 코드 구조로 드러내는 장치다. Mapper를 한 디렉터리에 모아 공용 변환기로 재사용하려 하기보다, 각 경계의 소유자에게 돌려주어야 한다. producer가 Contract를 만드는 변환은 producer 쪽에, consumer가 Contract를 자기 해석으로 바꾸는 변환은 consumer 쪽에, ORM과 도메인 타입 사이의 변환은 persistence 계층에 둔다.
from: 이 메모에 쓰인 생각을 만든 앞의 생각들입니다. 앞의 생각과 연관관계를 설명합니다.
1.
앞의 글은 ORM을 사용하면 프로젝트 초기에 DTO와 Mapper 보일러플레이트를 줄일 수 있다고 설명한다. 이 생각은 유효하다. 다만 그 다음 단계에서는 Mapper를 줄일 수 있는가보다 어떤 번역은 생략 가능하지만 어떤 번역은 오히려 명시적으로 남겨야 하는가를 구분해야 한다.
2.
LLM은 mapper를 만들라는 지시를 받으면 흔히 대칭적이고 범용적인 양방향 변환기를 만들려고 한다. 그러나 실제로 좋은 설계는 모든 변환을 일반화하는 데서 오지 않고, 어떤 변환이 공개이고 어떤 변환이 해석이며 어떤 변환이 단순한 persistence detail인지를 구분하는 데서 나온다.
supplementary: 이 메모에 작성된 생각을 뒷받침하는 생각의 새로운 메모입니다.
1.
opposite: 이 메모에 작성된 생각과 대조되는 생각의 새로운 메모입니다.
1.
to: 이 메모에 작성된 생각으로부터 발전된 생각의 새로운 메모입니다.
1.
ref: 생각에 참고한 자료입니다.
1.
영구메모 템플릿 버전 2026.03.20