웹 애플리케이션을 개발할 때 "사용자가 입력한 데이터는 어디로 가서 어떻게 처리될까?"라는 질문은 아키텍처 설계의 가장 기본이 되는 질문입니다. 이 데이터의 여정을 체계적으로 안내하는 지도가 바로 3-Tier 아키텍처이며, 이 여정에서 데이터를 안전하게 실어 나르는 전용 차량이 DTO(Data Transfer Object)입니다.
오늘은 웹 애플리케이션의 뼈대를 이루는 3가지 계층과, 각 계층 사이에서 데이터가 어떻게 DTO를 통해 안전하게 이동하는지 알아보겠습니다.
1. 애플리케이션의 3가지 핵심 계층
견고한 웹 애플리케이션은 보통 세 가지 주요 계층으로 역할을 나눕니다. 각 계층은 자신만의 명확한 책임이 있습니다.
① 프레젠테이션 계층 (Presentation Layer) - 고객을 맞이하는 창구
- 역할: 사용자와 직접 상호작용하는 UI 화면이나 API 엔드포인트를 제공합니다. 사용자의 요청을 가장 먼저 받고, 처리된 결과를 사용자에게 보여주는 역할을 합니다.
- 대표 컴포넌트: Spring의
Controller
② 서비스 계층 (Service Layer) - 실질적인 업무를 처리하는 사무실
- 역할: 애플리케이션의 핵심 비즈니스 로직을 처리합니다. 프레젠테이션 계층에서 받은 요청을 해석하고, 비즈니스 규칙에 따라 데이터를 가공하거나 계산을 수행합니다. 필요하다면 데이터 접근 계층에 데이터 처리를 요청합니다.
- 대표 컴포넌트:
Service
③ 데이터 접근 계층 (Data Access Layer) - 데이터를 보관하는 창고
- 역할: 데이터베이스와 직접 상호작용하며 데이터의 영속성(Persistence)을 관리합니다. 데이터를 생성(Create), 조회(Read), 수정(Update), 삭제(Delete)하는 CRUD 작업을 전담합니다.
- 대표 컴포넌트:
Repository
2. 데이터의 여정: 요청부터 응답까지
사용자가 '회원가입' 버튼을 눌렀을 때, 데이터는 다음과 같은 여정을 떠납니다.
요청 접수 (📥 프레젠테이션 계층)
사용자가 입력한 ID, 비밀번호 등의 데이터가 HTTP 요청을 통해 컨트롤러에 도착합니다. 이때 컨트롤러는 데이터를 DTO에 담아 받습니다.업무 지시 (⚙️ 프레젠테이션 계층 → 서비스 계층)
컨트롤러는 받은 DTO를 서비스 계층에 전달하며 "이 정보로 회원가입 비즈니스 로직을 처리해달라"고 요청합니다.데이터 처리 요청 (💾 서비스 계층 → 데이터 접근 계층)
서비스는 비즈니스 로직(예: 비밀번호 암호화)을 수행한 후, 가공된 데이터를 Entity 객체로 만들어 데이터 접근 계층(리포지토리)에 전달하며 "데이터베이스에 저장해달라"고 요청합니다.데이터 처리 결과 반환 (📤 데이터 접근 계층 → 서비스 계층)
리포지토리는 데이터베이스 작업을 마친 후, 저장된 Entity를 서비스 계층으로 반환합니다.결과 보고 (✅ 서비스 계층 → 프레젠테이션 계층)
서비스는 모든 비즈니스 로직을 완료한 후, 사용자에게 보여줄 결과(예: "회원가입 성공")를 다시 DTO로 변환하여 컨트롤러에 반환합니다.최종 응답 (✨ 프레젠테이션 계층 → 사용자)
컨트롤러는 서비스로부터 받은 DTO를 바탕으로 사용자에게 보여줄 최종 응답(JSON, HTML 등)을 생성하여 반환합니다.
3. DTO는 왜, 그리고 어디에 사용하는가?
DTO(Data Transfer Object)는 이름 그대로 계층 간 데이터 전송을 위한 전용 객체입니다. 그렇다면 데이터베이스와 직접 매핑되는 Entity를 그대로 사용하면 안 될까요? 정답은 "아니오" 입니다. DTO를 사용하는 이유는 다음과 같습니다.
Entity를 직접 노출하는 것은 우리 집의 모든 방 열쇠를 외부인에게 주는 것과 같습니다.
프레젠테이션 계층의 입력 데이터 처리
- 사용자 입력은 항상 유효하지 않을 수 있습니다. DTO를 사용하면
@Valid
어노테이션 등으로 유효성 검증을 DTO에서 처리할 수 있습니다. - Entity의 모든 필드가 아닌, 화면에 필요한 데이터만을 DTO로 정의하여 받을 수 있습니다.
- 사용자 입력은 항상 유효하지 않을 수 있습니다. DTO를 사용하면
서비스와 프레젠테이션 계층 간의 데이터 전달
- Entity는 데이터베이스와 관련된 민감한 정보(예: 비밀번호)나, 화면에는 불필요한 정보(예: 내부 식별자)를 포함할 수 있습니다. DTO를 사용하면 화면에 필요한 데이터만 선택적으로 가공하여 전달함으로써 보안을 강화하고 API 스펙을 명확하게 할 수 있습니다.
외부 API와의 통신
- 외부 시스템과 데이터를 주고받을 때, 상대방의 API 명세에 맞는 DTO를 사용함으로써 우리 시스템의 내부 데이터 구조(Entity)와 외부를 완벽하게 분리할 수 있습니다.
요약: Entity와 DTO의 명확한 경계
구분 | Entity | DTO (Data Transfer Object) |
---|---|---|
역할 | 데이터베이스와 매핑되는 핵심 도메인 객체 | 계층 간 데이터 전송을 위한 래퍼(Wrapper) 객체 |
핵심 로직 | 비즈니스 로직을 포함할 수 있음 (Domain-Driven) | 순수 데이터 컨테이너 (Getter/Setter만 존재) |
주요 사용 계층 | 서비스 계층, 데이터 접근 계층 | 프레젠테이션 계층과 서비스 계층 경계 |
생명주기 | 데이터베이스와 함께하는 영속적인 상태 | 요청과 응답 사이에서 생성되고 소멸됨 |
마치며
3-Tier 아키텍처와 DTO는 단순히 코드를 나누는 규칙이 아니라, 각자의 역할과 책임을 명확히 하여 유지보수하기 쉽고, 확장 가능하며, 안전한 애플리케이션을 만들기 위한 설계 철학입니다.
'프로그래밍 언어 > java' 카테고리의 다른 글
[Java] 도메인 계층 vs 서비스 계층 (0) | 2024.08.24 |
---|---|
[Java] Java의 String은 왜 불변(Immutable)할까? (0) | 2024.08.18 |
[Java] equals overriding 과 hash code (0) | 2024.08.11 |
[Java] final과 static: '불변'과 '공유'의 미학 (feat. JVM 메모리 구조) (0) | 2024.07.28 |
[Java] JVM 메모리 구조 파헤치기 (0) | 2024.07.28 |