본문 바로가기
공부할 것 !

Entity <-> DTO 변환

by sejin2 2025. 2. 5.

1. Dto에서 Entity로 변환

 

UserEntity

package com.basic.GADI.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.DynamicInsert;

import java.util.List;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@DynamicInsert
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;

    @Column(nullable = false)
    private String userName;

    @Column(unique = true)
    private String userEmail;

    @Column(nullable = false)
    private String userPw;

    private String userFile;

    @Column(nullable = false)
    @ColumnDefault("'U'")
    private String userRole;

    @OneToMany(mappedBy = "user")
    private List<Favorites> favorites;

}

 

회원가입 처리를 위한 Dto ( RegisterRequestDto )

 

package com.basic.GADI.dto.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.*;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RegisterRequestDto {

    @NotBlank(message = "아이디는 필수 입력 값입니다.")
    @Pattern(regexp = "^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$", message = "아이디는 이메일 형식입니다.")
    private String userEmail;

    @NotBlank(message = "이름은 필수 입력 값입니다.")
    private String userName;

    @NotBlank(message = "비밀번호는 필수 입력 값입니다.")
    @Pattern(regexp = "^[A-Za-z0-9]{6,12}$", message = "비밀번호는 숫자, 문자 포함의 6~12자리로 입력해주세요.")
    private String userPw;
    
    @Pattern(regexp = "^010-[0-9]{4}-[0-9]{4}$", message = "전화번호 형식은 010-1234-5678 입니다.")
    private String userPhone;

    @Pattern(regexp = "^(19\\d{2}|20\\d{2})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", message = "생년월일 형식은 YYYY-MM-DD 입니다.")
    private String userBirth;

}

 

기존 AuthService 에서 Dto를 Entity로 변환하기 위해 builder를 사용해서 넣어주었다.

AuthService

 User registerUser = User.builder()
                .userEmail(registerRequestDto.getUserEmail())
                .userName(registerRequestDto.getUserName())
                .userPw(passwordEncoder.encode(registerRequestDto.getUserPw()))
                .build();

        userRepository.save(registerUser);

 

-> 서비스단에 코드가 길어짐

-> 좀 더 간결하게 하기 위해  Dto를 Entity로 변환하는 코드를 Dto 내부에 메서드로 만들어 준다.

 

1) 생성자 사용

UserEntity에 필요한 변수의 생성자를 추가해준다. 

 // toRegisterRequestDto()에서 사용하기 위한 생성자
    public User(String userEmail, String userName,
                String userPw, String userPhone, String userBirth) {
        this.userEmail = userEmail;
        this.userName = userName;
        this.userPw = userPw;
        this.userPhone = userPhone;
        this.userBirth = userBirth;

RegisterRequestDto에 toRegisterRequestDto() 메서드 생성

public User toEntity(String encodedPw) {
    return new User(
        this.userEmail,
        this.userName,
        encodedPw,
        this.userPhone,
        this.userBirth
    );
}

 

 

2) 그대로 builder 사용

RegisterRequestDto 에 toRegisterRequestDto(String encodedPw) 메서드 생성 

 // Dto 에서 Entity 로 변환
    public User toRegisterRequestDto(String encodedPw) {
        return User.builder()
                .userEmail(userEmail)
                .userName(userName)
                .userPw(encodedPw)
                .userPhone(userPhone)
                .userBirth(userBirth)
                .build();
    }

AuthService

 String encodedPw = passwordEncoder.encode(registerRequestDto.getUserPw());

        User registerUser = registerRequestDto.toRegisterRequestDto(encodedPw);

        userRepository.save(registerUser);

 

2. Entity에서   Dto로 변환

 

기존 코드 - UserService

 public MyInfoResponseDto findMyInfo(Long userId) {
        Optional<User> findUserOne = userRepository.findById(userId);
        if (findUserOne.isEmpty()) {
            throw new BusinessException("해당 사용자를 찾을 수 없습니다.", HttpStatus.NOT_FOUND);
        }
        MyInfoResponseDto responseDto = new MyInfoResponseDto();
        responseDto.setUserName(findUserOne.get().getUserName());
        responseDto.setUserEmail(findUserOne.get().getUserEmail());
        responseDto.setUserFile(findUserOne.get().getUserFile());
        responseDto.setUserPhone(findUserOne.get().getUserPhone());
        responseDto.setUserBirth(findUserOne.get().getUserBirth());
        return responseDto;
    }

 

1) MyInfoResponseDto - 정적 메서드 방식 : 간결한 변환

// User Entity 에서 Dto 로 변환
public static MyInfoResponseDto fromUser(User user) {
    return new MyInfoResponseDto(
            user.getUserName(),
            user.getUserEmail(),
            user.getUserFile(),
            user.getUserPhone(),
            user.getUserBirth()
    );
}

 

메서드 생성 후 UserService

public MyInfoResponseDto findMyInfo(Long userId) {
        Optional<User> findUserOne = userRepository.findById(userId);
        if (findUserOne.isEmpty()) {
            throw new BusinessException("해당 사용자를 찾을 수 없습니다.", HttpStatus.NOT_FOUND);
        }
        return MyInfoResponseDto.fromUser(findUserOne.get());
    }

 

 

2) builder 사용 방식 : 가독성과 유지보수에 좋음

public static MyInfoResponseDto fromUser(User user) {
    return MyInfoResponseDto.builder()
            .userName(user.getUserName())
            .userEmail(user.getUserEmail())
            .userFile(user.getUserFile())
            .userPhone(user.getUserPhone())
            .userBirth(user.getUserBirth())
            .build();
}

 

 

📌 @Builder 패턴이 뭐야?

👉 객체를 생성할 때 필드 값을 유연하게 설정할 수 있도록 도와주는 패턴
👉 생성자의 단점을 보완하고, 가독성과 유지보수를 쉽게 해줌


🚀 @Builder를 쓰는 이유 (왜 필요할까?)

  1. 필드가 많으면 생성자 호출이 헷갈림
User user1 = new User("test@email.com", "홍길동", "1234", "010-1234-5678", "2000-01-01"); 
User user2 = new User("test2@email.com", "이순신", "5678", "010-5678-1234", "1995-05-05");

 

✅ 필드 순서를 맞춰야 해서 어떤 값이 어떤 필드인지 헷갈릴 수 있음!

  1. 필드가 많으면 setter()로 하나하나 설정하는 것도 귀찮음
User user = new User(); 
user.setUserEmail("test@email.com"); 
user.setUserName("홍길동"); 
user.setUserPw("1234"); 
user.setUserPhone("010-1234-5678"); 
user.setUserBirth("2000-01-01");

 

✅ 코드가 길어지고 객체가 불변(immutable)하지 않음


✅ @Builder 사용하면 이렇게 깔끔해짐!

User user = User.builder() 
		.userEmail("test@email.com") 
        .userName("홍길동") 
        .userPw("1234") 
        .userPhone("010-1234-5678") 
        .userBirth("2000-01-01") 
        .build();

 

필드 순서를 신경 쓰지 않아도 됨
가독성이 좋아짐
객체가 불변(immutable)하게 유지됨

'공부할 것 !' 카테고리의 다른 글

[오류] 415 (Unsupported Media Type)  (0) 2024.09.23
[오류] java.lang.IllegalStateException  (0) 2024.09.20
chart.js를 이용해 데이터 시각화하기  (0) 2024.08.23
AOP  (0) 2024.08.22
Maven, 형상관리  (0) 2024.08.20