안녕하세요~ DTO가 도대체 무엇인지 포스팅을 작성하면서도 어려웠던 느낌을 많이 받았습니다. 학교에서 자바를 배우게 되면서 DTO에 대해 잠시 배웠지만 제가 이해하는 영역에서는 접근 할 수 없었습니다. 이번 기회에 DTO에 대한 내용을 숙지하고자 합니다.
📑목차
1. DTO란 무엇인가?
1-1. DTO의 정의
1-2. DTO가 필요한 이유
1-3. NestJS에서 DTO가 사용되는 위치
1-4. 간단한 DTO 작성 예시
2. Class와 Interface 간단 정리
2-1. Class란 무엇인가?
2-2. Interface란 무엇인가?
2-3. Class와 Interface의 차이점
2-4. 왜 DTO는 Interface가아닌 Class로 작성할까?
서론
NestJS를 배우다 보면 Controller, Service, Module 만큼 자주 마주치는 개념이 바로 DTO입니다. API 개발에서 데이터를 주고받는 과정은 매우 빈번하기 때문에, DTO를 이해하면 전체 코드 흐름이 훨씬 명확해지고 실수도 줄일 수 있습니다. 또한 NestJS에서 DTO는 Class로 작성하는데, 그 이유를 이해하려면 TypeScript의 Class와 Interface의 차이도 알아야 합니다. 이 글에서는 가장 기본적이면서도 꼭 알고 있어야 하는 DTO, 그리고 Class와 Interface에 대해 간단하고 명확하게 설명해보겠습니다.
본론
1. DTO란 무엇인가?
1-1. DTO의 정의
DTO는 클라이언트와 서버 사이에서 주고받는 데이터의 형태를 정의한 객체입니다.
예를 들어 브라우저에서 사용자가 회원가입 버튼을 눌러 요청을 보내면, 서버는 그 요청이 어떤 형태(email, password 등)로 와야 하는지를 DTO로 정의합니다. 즉, 백엔드에서 "이런 형태의 데이터를 보내야 합니다(Request)"라고 요구하는 것이 DTO입니다. 필요하다면 응답(Response) 데이터도 DTO로 정의할 수 있으며, 이 경우 서버는 “이런 형태로 응답할 거다"라고 DTO로 명확하게 표현할 수 있습니다.
1-2. DTO가 필요한 이유
DTO를 왜 그럼 필요로 요구되는 이유는 무엇일까요?
DTO가 필요한 이유는 요청(Request)과 응답(Response)에서 사용되는 데이터 구조를 명확하게 정의하고, API 전체의 일관성을 유지하기 위해서입니다. 또한 DTO를 사용하면 잘못된 데이터가 서버 내부 로직에 들어오기 전에 검증할 수 있어 안전하고 안정적인 API를 만들 수 있기 때문입니다.
1-3. Nest.JS에서 DTO가 사용되는 위치
NestJS에서 DTO는 주로 Controller와 Service 사이에서 사용됩니다. 즉, 클라이언트가 보낸 요청(Request) 데이터를 Controller가 받을 때 DTO로 구조를 정의하고,이 데이터를 Service로 전달하여 비즈니스 로직을 처리할 수 있습니다.
또한, 필요하다면 응답(Response) 데이터 구조도 DTO로 정의하여, 서버가 반환하는 데이터의 형태를 명확하게 하고, 프론트엔드와의 API 약속을 일정하게 유지할 수 있습니다.
1-4. 간단한 DTO 작성 예시
게시판을 생성하는 DTO 구조
export class CreateBoardDtO {
title : string;
description : string;
}
Controller 로직
@Post()
// 게시물 생성하는 메서드
createBoard(
@Body() CreateBoardDtO:CreateBoardDtO
): Board {
return this.boardsService.createBoard(CreateBoardDtO);
}
Controller에서 지금 Body로 DTO 데이터 구조로 응답을 받고 있습니다. 이것을 그대로 Service에게 전달합니
Service 로직
createBoard(createBoardDtO:CreateBoardDtO) {
const {title, description} = createBoardDtO
const board: Board = {
id: uuid(),
title,
description,
status: BoardStatus.PUBLIC,
};
this.boards.push(board);
return board;
}
그럼 Service에서는 DTO에 대한 응답 데이터 구조에 대한 로직을 처리하게 됩니다.
2. Class와 Interface 간단 정리
왜 DTO가 Class와 Interface가 관련이 있을까요?
프로그래밍을 하다 보면 Class, Interface, 그리고 DTO라는 단어가 자주 함께 등장합니다. 처음 보면 “얘네들이 서로 무슨 관계지?”라는 생각이 들 수 있는데요. 사실 DTO라는 개념은 데이터의 모양을 정의하는 방식과 깊은 관련이 있기 때문에 자연스럽게 Class와 Interface를 함께 이야기하게 됩니다.
2-1. Class란 무엇인가?
우리가 흔히 Class라고 부르는 것은 속성과 기능을 모두 가지고 있는 설계도입니다. new 키워드로 실제 객체를 만들어낼 수도 있고, 필드와 메서드를 모두 포함할 수도 있죠.
2-2. Interface란 무엇인가?
반대로 Interface는 데이터가 가져야 할 칸만 정의하는 종이 양식 같은 존재입니다. 타입을 체크하는 데 유용하지만, 런타임에서는 사라지고 아무 기능도 하지 않죠. 즉, 타입 체크용으로만 존재하는 구조라는 점이 포인트입니다.
2-3. Class와 Interface의 차이점
프로그래밍에서 Class와 Interface는 자주 함께 이야기되지만, 둘은 분명히 다른 목적을 가지고 있습니다. 쉽게 말하면 Class는 실제로 동작하는 설계도, Interface는 약속만 정의하는 규칙서라고 생각하면 이해가 훨씬 편해집니다.
2-4. 왜 DTO는 Interface가아닌 Class로 작성할까?
프론트엔드에서는 DTO를 Interface로 정의해도 큰 문제가 없지만, 특히 NestJS나 백엔드 환경에서는 DTO를 거의 항상 Class로 작성합니다. 그렇다면 왜 굳이 Class를 사용할까요?
이유는 단순합니다. Interface는 타입만 존재하고, 런타임에서는 사라지기 때문입니다. 런타임이란 프로그램이 실행되는 동안을 말합니다. 일반적으로 타입스크립트는 컴파일 후 자바스크립트로 변환됩니다. Interface는 타입 검사할때 주로 작성되어 실제로 프로그램이 동작되면 아무런 변화가 없다는 뜻입니다.
결론
인터페이스는 개발 단계에서만 필요한 약속일 뿐 런타임에는 사라진다는 점을 다시 한 번 느꼈고, 반대로 클래스는 실행 중에도 실제로 남아 동작하기 때문에 DTO에 더 적합하다는 사실이 확실해졌고, 결국 형태만 필요할 때는 인터페이스, 실제 검증과 동작이 필요할 때는 클래스를 선택해야 한다는 기준이 더 명확해진 것 같다라는 것을 느낄 수 있었습니다.
'Next.js 기록' 카테고리의 다른 글
| Next.js 에서 동적 라우팅과 중첩 라우팅 완벽 가이드 (0) | 2025.08.06 |
|---|---|
| Next.js의 렌더링 구조 이해하기!! 서버 컴포넌트, 클라이언트 컴포넌트, 프리렌더링, 하이드레이션까지 (12) | 2025.08.04 |
| Next.js 란 무엇인가? (2) | 2025.07.30 |