Spring 기본 - DTO (Data Transfer Object) 패턴

2025. 9. 20. 18:36·개발 아카이브/JAVA
반응형

https://wooncloud.tistory.com/161

 

Spring 기본 시작 - 세팅부터 CRUD API 까지

1. 자바 설치 (Java JDK 17 이상 설치)Java 8 (2014년 출시)여전히 많은 기업에서 레거시 시스템으로 사용 중람다 표현식, Stream API 등 중요한 기능이 도입된 버전장기적으로는 점차 마이그레이션하는 추

wooncloud.tistory.com

https://wooncloud.tistory.com/162

 

Spring 기본 - Service 계층

이전 내용https://wooncloud.tistory.com/161 Spring 기본 시작 - 세팅부터 CRUD API 까지1. 자바 설치 (Java JDK 17 이상 설치)Java 8 (2014년 출시)여전히 많은 기업에서 레거시 시스템으로 사용 중람다 표현식, Stream

wooncloud.tistory.com

DTO (Data Transfer Object) 패턴

 

왜 DTO가 필요할까?

  • 보안: Entity의 모든 필드를 노출하지 않음
  • 성능: 필요한 데이터만 전송
  • 유연성: API 응답 형식을 자유롭게 조정
  • 분리: Entity 변경이 API에 영향주지 않음

1. DTO 패키지와 클래스 생성

src/main/java/com/example/demo_api에 dto 패키지를 생성

 

2-1. UserDto.java 클래스 생성

package com.example.demo_api.dto;

public class UserDto {
    private Long id;
    private String name;
    private String email;
    
    // 기본 생성자
    public UserDto() {}
    
    // 모든 필드 생성자
    public UserDto(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
    
    // getter, setter
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

 

2-2. 요청용 DTO도 생성 - CreateUserRequest.java

package com.example.demo_api.dto;

public class CreateUserRequest {
    private String name;
    private String email;
    
    // 생성자, getter, setter 동일하게 작성
}


3. DTO 변환 유틸리티 메소드 추가

UserService에 변환 메소드들을 추가.

// UserService.java에 추가
// Entity -> DTO 변환
private UserDto convertToDto(User user) {
    return new UserDto(user.getId(), user.getName(), user.getEmail());
}

// DTO -> Entity 변환  
private User convertToEntity(UserCreateDto userCreateDto) {
    return new User(userCreateDto.getName(), userCreateDto.getEmail());
}

// List<Entity> -> List<DTO> 변환
private List<UserDto> convertToDtoList(List<User> users) {
    return users.stream()
            .map(this::convertToDto)
            .collect(Collectors.toList());
}

그런데 이렇게 Entity를 DTO로 바꾸는게 너무 귀찮다.

이런 귀찮음을 모든 개발자들이 알고 있고, 그래서 이 귀찮음을 해결하기 위한 방법들이 있다.

  • ModelMapper
  • MapStruct

3-1. ModelMapper 사용

// build.gradle에 추가
implementation 'org.modelmapper:modelmapper:3.1.1'
@Service
public class UserService {
    
    @Autowired
    private ModelMapper modelMapper;
    
    // 변환이 이렇게 간단해짐!
    public UserDto createUser(UserCreateDto userCreateDto) {
        User user = modelMapper.map(userCreateDto, User.class);
        User savedUser = userRepository.save(user);
        return modelMapper.map(savedUser, UserDto.class);
    }
    
    public List<UserDto> getAllUsers() {
        return userRepository.findAll().stream()
                .map(user -> modelMapper.map(user, UserDto.class))
                .collect(Collectors.toList());
    }
}

 

3-2. MapStruct

(컴파일 시점에 생성, 성능 좋음)

@Mapper(componentModel = "spring")
public interface UserMapper {
    UserDto toDto(User user);
    User toEntity(UserCreateDto dto);
    List<UserDto> toDtoList(List<User> users);
}

 

3-3. 생성자 기반 변환

(간단하지만, Entity와 DTO에 들어있는 데이터가 많아지면 많아지고 복잡해짐.)

// DTO에 생성자 추가
public UserDto(User user) {
    this.id = user.getId();
    this.name = user.getName();
    this.email = user.getEmail();
}

 

저는 ModelMapper 라이브러리를 사용했습니다.

 

4. Controller를 DTO 사용으로 수정

UserController를 다음과 같이 수정한다.

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping
    public List<UserDto> getAllUsers() {  // UserDto 반환
        return userService.getAllUsers();
    }
    
    @PostMapping
    public UserDto createUser(@RequestBody UserCreateDto userCreateDto) {  // DTO 사용
        return userService.createUser(userCreateDto);
    }
    
    @GetMapping("/{id}")
    public UserDto getUserById(@PathVariable Long id) {  // UserDto 반환
        return userService.getUserById(id);
    }
    
    @PutMapping("/{id}")
    public UserDto updateUser(@PathVariable Long id, @RequestBody UserCreateDto userCreateDto) {
        return userService.updateUser(id, userCreateDto);
    }
    
    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Long id) {
        // 삭제는 그대로
        boolean deleted = userService.deleteUser(id);
        return deleted ? "사용자가 삭제되었습니다." : "사용자를 찾을 수 없습니다.";
    }
}

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'개발 아카이브 > JAVA' 카테고리의 다른 글

Spring 기본 - 게시판 만들기  (0) 2025.09.21
JAVA equals, hashCode 오버라이드시 instanceof와 getClass 차이  (0) 2025.09.21
Spring 기본 - Service 계층  (0) 2025.09.20
Spring 기본 시작 - 세팅부터 CRUD API 까지  (2) 2025.09.04
Java 17 다운로드 방법  (0) 2025.09.03
'개발 아카이브/JAVA' 카테고리의 다른 글
  • Spring 기본 - 게시판 만들기
  • JAVA equals, hashCode 오버라이드시 instanceof와 getClass 차이
  • Spring 기본 - Service 계층
  • Spring 기본 시작 - 세팅부터 CRUD API 까지
운클라우드
운클라우드
프로그래밍, 디자인 및 각종 이야기와 리뷰를 담는 블로그
  • 운클라우드
    Wooncloud Blog
    운클라우드
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 이야기
        • 일기
        • 개발일지
        • 제품 리뷰
        • 기타
        • 정보처리기사
      • 정보
        • 유용한 사이트
      • 개발 아카이브
        • AI, 인공지능
        • Javascript
        • JAVA
        • DATABASE
        • 개발 관련 지식
        • 라이브러리
        • AWS, Cloud, Server
        • 코드 저장소
        • HTML, CSS
  • 블로그 메뉴

    • 홈
    • 방명록
    • 운구름 웹
    • 벨로그
    • 깃허브
    • 리틀리
    • 도시부엉
  • 링크

    • 홈페이지
    • 깃허브
    • 벨로그
  • 공지사항

  • 인기 글

  • 태그

    spring
    스터디
    CSS
    자바
    javascript
    라이브러리
    Java
    html
    튜닝
    폰트
    API
    Ai
    정보처리기사
    SQL
    회고
    웹디자인
    스프링
    json
    자바스크립트
    코드저장소
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
운클라우드
Spring 기본 - DTO (Data Transfer Object) 패턴
상단으로

티스토리툴바