26/07/20 IL(I Learned) - Step 2

DTO와 Entity를 활용한 계층 간 데이터 전달

Spring MVC 프로젝트에서 Entity와 DTO(Data Transfer Object)를 분리하여 사용하는 이유를 학습하였다. 이전 JDBC 프로젝트에서는 Repository가 반환한 Entity를 그대로 사용하였지만, 이번 프로젝트에서는 사용 목적에 따라 AccountFormDTO, AccountUpdateDTO, AccountViewDTO를 각각 따로 만들어 사용하였다.

사용자의 입력을 받는 객체와 화면에 보여주는 객체, 그리고 실제 데이터베이스에 저장되는 객체는 서로 역할이 다르다는 점을 이해하게 되었다.

또한 Java Record를 이용하여 DTO를 작성하면서 불필요한 코드를 줄이고, Builder Pattern을 이용해 Entity를 생성하는 방법도 함께 익힐 수 있었다.


1) Account(Entity)

학습 내용상세 내용
Entity데이터베이스 테이블과 직접 연결되는 객체이다.
@Builder객체 생성 시 필요한 값만 선택하여 생성할 수 있도록 도와주는 Lombok 기능이다.
@Getter / @Setter필드에 직접 접근하지 않고 메서드를 통해 값을 읽고 수정한다.
객체지향 캡슐화데이터를 객체 내부에서 관리하도록 하여 유지보수성을 높인다.
DB와 매핑Account 객체 하나가 accounts 테이블의 한 행(Row)을 의미한다.
@Getter
@Setter
@Builder
public class Account {

    private long accountId;

    private String accountName;

    private String createdDate;

}

Account Entity는 데이터베이스의 accounts 테이블과 대응되는 객체이다.

예를 들어 데이터베이스에 다음과 같은 데이터가 있다고 가정해 보자.

idnamecreated_at
1홍길동2026-07-20

Repository가 이 데이터를 조회하면 다음과 같은 객체가 만들어진다.

Account account = Account.builder()
        .id(1L)
        .name("홍길동")
        .createdAt("2026-07-20")
        .build();

Entity는 데이터베이스의 실제 데이터를 표현하는 객체이기 때문에 CRUD 과정에서 가장 많이 사용된다.

이번 프로젝트에서는 Lombok의 @Builder를 활용하여 객체를 생성하였다.

Builder Pattern을 사용하면 생성자의 매개변수 순서를 기억할 필요가 없으며, 필요한 값만 선택적으로 설정할 수 있어 코드의 가독성이 크게 향상된다.


Entity의 역할

Database

↓

Account(Entity)

↓

Repository

↓

Service

Entity는 항상 Repository와 Service 사이에서 실제 데이터를 전달하는 역할을 수행한다.


Builder Pattern을 사용하는 이유

일반 생성자Builder Pattern
매개변수 순서를 기억해야 함이름으로 값을 지정할 수 있음
가독성이 떨어질 수 있음읽기 쉽고 유지보수가 편리함
일부 값만 설정하기 어려움필요한 값만 설정 가능

느낀 점내용
Entity의 역할단순한 객체가 아니라 데이터베이스의 한 행(Row)을 표현하는 중요한 객체라는 점을 이해하였다.
Builder Pattern생성자보다 Builder를 사용하는 것이 훨씬 읽기 쉽고 유지보수하기 편리하다는 것을 느꼈다.
객체지향 설계데이터를 객체로 관리하는 것이 코드의 안정성과 가독성을 높여준다는 점을 배웠다.

2) AccountFormDTO & AccountUpdateDTO

📚 오늘 배운 내용

학습 내용상세 내용
DTO(Data Transfer Object)계층 간 데이터를 전달하기 위한 객체이다.
FormDTO사용자가 입력한 데이터를 저장하는 객체이다.
UpdateDTO수정 시 필요한 데이터(id, 변경 값)를 전달하는 객체이다.
RecordDTO를 간결하게 작성하기 위해 사용하였다.
데이터 검증DTO를 이용하면 입력값 검증과 데이터 전달을 분리할 수 있다.
public record AccountCreateDTO(
        String accountName
) {
}
public record AccountModifyDTO(

        long accountId,

        String accountName

) {
}

DTO를 하나만 사용하지 않고 용도에 따라 분리하였다.

1. 계좌 생성

계좌를 생성할 때는 사용자가 입력하는 값이 이름뿐이다.

이름 입력

↓

AccountFormDTO

따라서 id는 필요하지 않다.


2. 계좌 수정

수정은 다르다.

어떤 계좌를 수정할지 알아야 하기 때문에

id

+

변경할 이름

두 정보가 모두 필요하다.

그래서

AccountUpdateDTO

를 별도로 만들었다.

이처럼 작업 목적에 따라 DTO를 분리하면 필요한 데이터만 전달할 수 있어 코드가 더욱 명확해진다.


DTO를 분리하는 이유

DTO사용하는 상황
FormDTO생성(Create)
UpdateDTO수정(Update)
ViewDTO조회(Read)

각 DTO는 하나의 목적만 수행하도록 설계하였다.


Record를 사용하는 이유

DTO는 데이터를 저장하고 전달하는 역할만 수행한다.

따라서

  • Getter
  • equals()
  • hashCode()
  • toString()

이 자동 생성되는 Record가 매우 적합하다.

코드도 훨씬 간결해진다.

실무에서도 요청(Request)마다 DTO를 분리하는 경우가 많다.

예를 들어 회원 기능이라면 다음과 같이 구성할 수 있다.

  • MemberCreateRequest
  • MemberUpdateRequest
  • MemberLoginRequest
  • MemberResponse

하나의 DTO를 재사용하기보다 기능별로 DTO를 분리하여 관리하는 것이 일반적이다.

느낀 점내용
DTO 분리같은 Account라도 용도에 따라 다른 DTO를 사용하는 이유를 이해하였다.
Record 활용DTO 작성 시 코드가 훨씬 간결해지고 가독성이 좋아졌다.
유지보수목적에 맞게 DTO를 분리하면 변경 범위가 줄어든다는 점을 배웠다.

3) AccountViewDTO

학습 내용상세 내용
ViewDTO화면에 보여줄 데이터를 전달하는 DTO이다.
fromEntity()Entity를 ViewDTO로 변환하는 정적 메서드이다.
Entity 보호Entity를 View에 직접 노출하지 않도록 한다.
EL(Expression Language)JSP에서 객체의 값을 출력하기 위한 표현식이다.
public static AccountViewDTO fromEntity(Account entity){

    return new AccountViewDTO(

            entity.getId(),

            entity.getName(),

            entity.getCreatedAt()

    );

}

Service에서는 Repository가 반환한 Entity를 그대로 JSP에 전달하지 않는다.

대신

Entity

↓

ViewDTO

↓

JSP

순서로 변환한다.

이 과정을 담당하는 메서드가

fromEntity()

이다.

즉,

Account

객체를

AccountViewDTO

로 변환하는 역할을 수행한다.


왜 Entity를 직접 넘기지 않을까?

예를 들어 Entity에 다음과 같은 정보가 추가되었다고 가정해 보자.

  • password
  • 주민등록번호
  • 계좌 비밀번호

이 객체를 그대로 View에 전달하면 민감한 정보가 노출될 수 있다.

하지만 ViewDTO에는 필요한 데이터(id, name, createdAt)만 담기므로 불필요한 정보의 노출을 막을 수 있다.


Entity와 DTO의 관계

Database

↓

Entity

↓

Repository

↓

Service

↓

ViewDTO

↓

Controller

↓

JSP

느낀점

느낀 점내용
DTO의 중요성Entity와 화면을 분리하면 보안과 유지보수성이 모두 향상된다는 점을 이해하였다.
fromEntity()객체를 다른 객체로 변환하는 패턴을 익힐 수 있었다.
MVC 구조Controller와 View 사이에서도 DTO를 사용하는 이유를 명확하게 이해하게 되었다.
profile
예 마 함 가보입시더

0개의 댓글