반응형

DTO(Data Transfer Object)란?

DTO(Data Transfer Object)는 계층 간 데이터를 전달하기 위한 객체입니다. 서비스 계층과 컨트롤러 계층 간의 데이터 전송을 쉽게 하기 위해 사용됩니다. DTO는 엔티티(Entity)와 분리되어 있어, 불필요한 데이터 노출을 방지하고, 데이터 변환 및 검증을 용이하게 합니다.


DTO의 구조

DTO는 다양한 방식으로 정의할 수 있으며, 대표적인 구조는 다음과 같습니다.

1. record를 활용한 DTO (Java 14+)

record는 불변성을 보장하며, 자동으로 생성자, getter, toString 등을 제공하는 DTO 구현 방식입니다.

예제:

public record UserDTO(Long id, String name, String email) {}

위와 같이 정의하면 UserDTO는 불변 객체가 되며, getter 메서드가 자동으로 생성됩니다.


2. 내부 클래스(Inner Class)로 DTO 정의

내부 클래스를 활용하면 DTO를 특정 컨트롤러 또는 서비스 내에서만 사용할 수 있어, 가독성과 응집도를 높일 수 있습니다.

예제:

public class UserDto {
    public static class Request {
        private String name;
        private String email;

        public Request(String name, String email) {
            this.name = name;
            this.email = email;
        }
    }
    
    public static class Response {
        private Long idx;
        private String name;
        private String email;

        public Response(String name, String email) {
            this.name = name;
            this.email = email;
        }
    }
}

내부 클래스를 활용하면, RequestResponse를 한 파일에서 관리할 수 있습니다.


3. DTO 패키지 구조

대규모 프로젝트에서는 DTO를 별도의 패키지로 관리하는 것이 일반적입니다.

예제:

com.example.project
├── controller
│ ├── UserController.java
├── service
│ ├── UserService.java
├── dto
│ ├── UserRequestDTO.java
│ ├── UserResponseDTO.java

이처럼 dto 패키지를 분리하면 코드가 깔끔해지고, DTO의 역할이 명확해집니다.


DTO 활용 예제

DTO는 엔티티와 직접 연결되지 않으며, 서비스 계층에서 변환하여 사용합니다.

// Entity
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
}

// DTO
public record UserDTO(Long id, String name, String email) {}

// Service
@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
	    this.userRepository = userRepository;
	}

    public UserDTO getUserById(Long id) {
        User user = userRepository.findById(id).orElseThrow();
        return new UserDTO(user.getId(), user.getName(), user.getEmail());
    }
}

위 코드에서 UserServiceUserDTO를 반환하여, 컨트롤러에서 엔티티가 직접 노출되지 않도록 보호합니다.


마무리

DTO는 애플리케이션에서 데이터를 안전하게 전달하는 중요한 역할을 합니다. record, 내부 클래스, 패키지 분리를 활용하여 효율적인 DTO 설계를 적용할 수 있으며, 이를 통해 유지보수성과 보안성을 높일 수 있습니다.

 

반응형

+ Recent posts