2026-05-21
# TIL · 2026-05-21
> 오늘 위키 정리하면서 끝까지 짚인 것들. 발표자료/도식 만들면서 한 번 더 깎인 깨달음들이라
> 머리에 잘 남았다. 나중에 흐릿해지면 이 노트부터 다시 본다.
---
## 1. DTO의 필드 결정 기준은 "엔티티"가 아니라 "유스케이스"다
내가 가장 헷갈렸던 부분이고, 오늘 가장 또렷해진 부분.
처음엔 이렇게 생각했다 —
"DTO는 엔티티(행위)를 위해 어떤 필드가 필요한지 결정하는 거잖아?"
정확히는 틀렸다. DTO는 엔티티의 부속물이 아니다. 오히려 그 반대다.
> DTO의 존재 이유는 엔티티를 돕기 위해서가 아니라,
> 엔티티로부터 클라이언트를 격리하기 위해서다.
그래서 같은 Post 엔티티라도 DTO는 여러 개로 갈린다:
- PostAllResponseDto ← "목록 화면이 뭘 필요로 하는가" (body 없음)
- PostDetailResponseDto ← "상세 화면이 뭘 필요로 하는가" (전부)
- PostCreateRequestDto ← "글 작성 요청이 뭘 보내는가"
필드를 정하는 사람은 엔티티가 아니라 화면/요청 시나리오다.
이걸 잊으면 도메인이 바뀔 때마다 클라이언트가 같이 깨진다.
→ 위키 [[dto-vs-entity]]
---
## 2. "도메인"이라는 단어가 진짜 의미하는 것
"엔티티는 비즈니스 도메인의 본체"라고 적힌 글을 수없이 봤지만, 도메인이 정확히 뭔지
한 번도 명확히 짚지 않았다. 오늘 정리.
> 도메인 = 이 소프트웨어가 다루는 현실 세계의 영역.
> 코드가 아니라 현실에 먼저 존재하는 것.
쇼핑몰을 만든다면 도메인은 "온라인 쇼핑이라는 현실 세계의 영역"이다.
그 세계에는 회원·상품·장바구니·주문 같은 개념과,
"배송 완료된 주문은 취소 못 한다" 같은 규칙이 산다.
프로그래머는 그 세계를 코드로 옮기는 사람이다.
- 도메인 = 현실의 영역
- 도메인 모델 = 그 영역을 코드로 옮긴 객체 묶음
- 엔티티 = 도메인 모델 중 식별자(id)를 가진 핵심 객체
그래서 "엔티티가 비즈니스 로직과 직결된다"는 말은
= "엔티티는 도메인의 규칙을 자기 안에 품고 있어야 한다"가 된다.
Order.cancel()이 "배송 완료 시 취소 불가"를 아는 것처럼.
왜 굳이 "비즈니스 로직"이 아니라 "도메인"이라 부르나 —
"비즈니스 로직"은 코드 관점, "도메인"은 문제 관점이라서.
도메인이라는 단어를 쓰는 순간 자연스럽게 이런 질문이 따라온다:
> "이 코드는 도메인 전문가가 이해할 수 있는 언어로 쓰여 있나?"
이게 DDD(Domain-Driven Design)의 출발점이라는 것도 처음 알았다.
→ 위키 [[domain]]
---
## 3. DispatcherServlet은 결국 그냥 하나의 Servlet이다
이 사실 하나가 머릿속의 안개를 다 걷어냈다.
Spring을 보면 @Controller, @RestController, HandlerMapping, ViewResolver...
부품이 너무 많아서 "Servlet과 완전히 다른 세계인가?" 싶었는데, 사실은:
> DispatcherServlet은 Tomcat 위에 등록된 단 한 개의 Servlet이다.
> URL 패턴 /로 등록돼서, 모든 요청이 일단 이 친구에게 들어온다.
그리고 정작 자기는 직접 일을 안 한다. 4부품에 위임한다:
| 단계 | 부품 | 일 |
| --- | --- | --- |
| ① | HandlerMapping | URL → 어느 컨트롤러 메서드로 보낼지 결정 |
| ② | HandlerAdapter | 그 컨트롤러를 어떻게 호출할지 안다 |
| ③ | ViewResolver | 뷰 이름 → 실제 파일로 매핑 |
| ④ | HttpMessageConverter | 객체 ↔ JSON 변환 @ResponseBody일 때) |
이게 Front Controller 패턴. URL마다 Servlet을 따로 만드는 대신,
정문 하나로 모든 요청을 받고 거기서 공통 처리(인증·로깅·뷰 결정)를 표준화한다.
순수 Servlet 시대에 내가 doGetdoPost에서 손수 짜던 일들 —
파라미터 파싱, forward, JSON 응답 작성 — 이걸 전부 디스패처의 4부품이 대신해준다.
Spring MVC가 편하다고 느껴지는 이유의 90%가 여기에 있다.
→ 위키 [[dispatcher-servlet]]
---
## 4. DTO / DAO / Entity / DO — DAO만 "행동"이고 나머진 "객체"다
이름이 비슷해서 다 같은 종류인 줄 알았는데, 오늘 4종을 한 표로 정리하면서 진짜 분류 기준이 잡혔다.
> DTO, Entity, DO는 모두 "데이터를 담은 객체" (명사)
> DAO는 "데이터에 접근하는 동작"을 캡슐화한 객체 (사실상 동사)
| 구분 | 본질 | 행위 | 식별자(id) | DB 매핑 |
| --- | --- | --- | --- | --- |
| DTO | 운반체 | 없음 | 의미 약함 | 아님 |
| DAO | 행동(접근자) | findAll/save/... | 해당 없음 | 매핑을 수행 |
| Entity | 도메인 본체 | 있음 (규칙) | 핵심 | 대개 매핑됨 |
| DO | 도메인 객체 일반 | 있을 수 있음 | 경우에 따라 | 의무 없음 |
한 요청에서 네 객체가 만나는 자리:
```
[Controller] ── postDao.findById(42) ──▶ [DAO] ← 행동
│ SELECT ...
▼
[DB]
│
▼
[Entity] ← DB 한 행을 채운 도메인 본체
│ Service에서 변환
▼
[DTO] ← 응답용 운반체
```
DO와 Entity의 관계도 정리:
- 엄밀히는 DO ⊃ Entity ∪ VO. DDD 위계.
- Entity = 식별자로 구별 (주문 #42 ≠ 주문 #43)
- VO(Value Object) = 값으로 구별 (1000원짜리 두 개는 같은 1000원)
- 한국 실무에선 "DO"가 거의 안 쓰이거나 Entity와 동의어로 쓰임.
팀에서 DO가 등장하면 합의된 의미부터 확인할 것.
→ 위키 [[dto-vs-entity]] / [[domain]] / [[dao-pattern]]
---
## 5. MVC와 3-tier는 같은 것이 아니다
마지막으로 한 번 더 못박은 것. 이걸 모르면 Controller가 두 세계에 동시에 등장하는 게
계속 헷갈린다.
| 축 | 무엇을 나누나 | 분할 |
| --- | --- | --- |
| MVC | 표현(presentation) 분리 | Controller · View · Model |
| 3-tier | 시스템 계층 분리 | Web · Business · Data |
축이 다르기 때문에 두 분리는 동시에 적용된다.
Spring에서 @Controller는 MVC의 C이자 3-tier의 Web Layer 진입점.
그 아래로 @Service → @Repository가 이어지는 게 3-tier.
그 안에서 Controller와 View가 협력하는 게 MVC.
> 외워두기: MVC는 화면 쪽만 분리, 3-tier는 화면 안쪽까지 포함한 전체 분리.
→ 위키 [[mvc-pattern]] / [[three-tier-architecture]]
---
## 오늘 위키에 박은 것
- 신규: [[dispatcher-servlet]] · [[spring-mvc-request-flow]] · [[domain]]
- 보강: [[dto-vs-entity]] (4종 비교 + 유스케이스 기준 명시), [[domain]] (DO/VO/Entity 위계)
- 산출물: Output/2026-05-21-spring-mvc-도식.html — 5개 도식 + walkthrough
---
## 내일 / 다음에 이어볼 것
- [[dispatcher-servlet]]의 4부품 중 HandlerAdapter가 어떻게 다양한 핸들러 타입을
일관된 방식으로 호출하는지 — 어댑터 패턴의 교과서적 사례라고 들었으니 한 번 코드로 확인.
- Value Object를 미니 SNS 실습에 한 번 도입해보기 — Money나 Period 같은 거.
[[equals-hashcode]] 오버라이딩이 왜 VO에서 필수인지 직접 체감해보자.
- AOP — 아직 위키에 빈자리. DI/IoC와 함께 Spring의 양대 산맥이라는데, 다음 정리 후보.
댓글
댓글이 없습니다.
