DTO

가언·2024년 7월 22일

spring

목록 보기
6/8

<Rest API url 사용 규칙>

  • 동사는 사용 지양 ⇒ 행동은 method로 나타낸다
  • 복수, 단수 통일 ⇒ 프론트가 헷갈리니까!
  • _ 사용 금지 ⇒ 대신 하이픈(-) 사용
  • 소문자 사용 ⇒ 의미를 알아보기 쉽게 하기 위해
  • 마지막에 슬래시를 포함하지 않는다 ⇒ 후행 슬래시는 의미가 없다
  • URI 사이에 연관 관계를 있는 경우 /리소스/고유ID/관계있는리소스 순으로 작성
    ex) users/profile/{userId} (X) user/{userId}/profile (O)
  • 전세계적으로 "규칙" -> 무조건 지켜야한다? NO!

✅ DTO의 필요성을 느끼다..

회원 API 설계

  • 로그인
    - id,pw
    req: id/pw
    res: name
  • 회원가입
    - id, pw, name, email, address, contack
    req: 필드 전부
    res: id

    회원가입과 로그인에서 주고받는 정보가 다른데,,, User라는 하나의 객체만 생성하는건 비효율적이야! 그럼 객체를 여러개 만들어야 할까..? 그럼 DB도 여러개를 만들어야 하나...?!? 🤯 어떡해야하지 ->DTO가 해결: 객체를 변환(아직 코드 완성은 못함..to be continued..)

어떻게 객체를 변환할 것인가?

  • 어디서(클래스 위치)?

  • 어떻게(방법)?
    - 생성자
    - 빌더의 장점=생성자의 단점: 파라미터에 뭘 넣어야 할 지 모름

    • setter
    • copy product : 생성자, builder, setter
    • map contructor
  • +객체 분리 기준/각 역할

✅ DTO가 왜 필요할까?

하나의 객체, 데이터가 repository까지 들어갔을 때 장점? 단점?
단점:

  • 클라이언트에게 굳이 ~ 전달되지 않아도 되는 데이터 포함
    ex. 시스템 활용 데이터(생성/수정 일시) -> 네트워크 비용만 올라가고, 보안 안 좋음 (hint. 극단적으로 생각해보기!)
  • 클라이언트가 필요한 데이터 미포함
    ex. 구현 코드 연관관계 X -> 화면에는 같이 뿌려줘야 하는 경우
    ex. 생년월일->나이

1️⃣ 예시1) req->dto안에 사용하는 필드만 넣어서 통채로 반환
서비스 코드를 바꾸지 않게 전달 가능
먼저, a 객체가 그대로 db로 들어감 처음 ui/ux에 맞춰져서 설계됨.
이후, 화면 단에 하나가 더 추가되었을 경우, 입력을 받았는데 db저장 용도가 아니 연산하려는 용도일 경우
(예를 들어, mbti, 저축, 자산, 대출, 부동산와 같은 정보) 종합적으로 평가 db에 "소비성향"으로 저장해두는 경우)
즉, 당장 db에 저장할 것은 아닌데 화면 단의 내용이 바뀌는 경우

  • 일단은 시스템 안쪽까지 들고오는게 문제가 됨!
  • 해결: 중간에 끊으면 앞까지만 변경하면 됨. 그 이후의 로직을 따로 가지고 가도록 중간에서 하나의 객체를 더 만들어 처리할 수 있도록 함!

2️⃣ 예시2) 스키마 이름 바꾸는 일
password-> pwd 컬럼명을 바꾸었을 때 프론트엔드까지 바꿔야하는 상황 발생.
중간에 끊어서 프론트엔드에서는 여전히 같은 컬럼명 사용 가능하고, 중간에 전환 로직을 추가하는 것이 좋음!

결론

아래의 예시에서 단일 책임의 원칙이 깨지지 않게 하기 위해 DTO가 필요하다!
단일 책임 원칙: 수정은 하나의 actor만 존재해야 함!
1) client 무슨 일 생겼을 때 -> DB까지
db에 그대로 저장될 데이터는 아님 필드를 추가해도 되니?
2) DB에 무슨 일 생겼을 때 -> client가 알아야 해?
(DB 컬럼 이름이 바뀌면, 클라이언트 호출도 바껴야 함?)
➡️ 데이터를 옮기는 객체가 하나일 경우 여러 계층에서 그 객체에 수정을 가하면 단일 책임 원칙이 바로 깨진다!

정리해서..DTO(Data Transfer Object) 특징은?

  • 데이터 전송용 객체 = 엔티티(Entity)의 사본

  • setter: 되도록이면 사용하지 말자!
    setter 사용시 언제든 누구나 값을 변경할 수 있어 DB의 사용이유인 '무결성'을 위반하기때문!
    - DB -> (Object: setter 포함)->Client
    +DB 쓰는 이유? 보안, 무결성

  • Q. setter를 DTO가 절대 가지면 안될까요?
    NOPE! 절대는 NOPE!
    그럼 언제써야할까? update할 때 사용가능!!

Entity(이자 Domain Object인 친구)

  • 데이터 원본 from DB
  • DB로 들어갈/연산이 끝난 (=원본이 될 ) 객체
    강형욱: DTO, 박완규: Entity

- JPA > jdbc Entity..? 왜...?

✅ 그렇다면 DTO <-> Entity 어디서 바뀌는 걸까?

  • 원본 이름 : 엔터티
  • 전송일때 DTO
  • Client->Controller->Service->Repository->DB
  • DB->Repository->Service->Controller->Client
  • 입장1: controller에서 변환되는거야!
    : request, response를 받는 역할인데 연산을 왜해?
    서비스에서 dto로 바꾼다는 건 클라이언트꺼까지 고민해야한다는 건데 왜 service에서 클라이언트를 굳이 고민해야해?
  • 입장2: service에서 변환되는 거야!
    :DTO와 Entity를 변환하는 것은 연산이므로 이는 Service의 책임이라고 생각해!
  • 입장3: repository에서 변환되는 거야!
    : 이동할때 dto사용하는거라며!! 그럼 repository로 부터 나온 결과를 service에 전달할때도 필요하잖아~!

controller, service, repository 모두 다 가능!

🌟 미리보기

  • A service->B Service ❌: 의존성 존재, 서로가 없으면 못 돌아간다는 것! 잘못된 설계!
  • A controller-> B Service 🅾️
  • A Service-> B repository 🅾️
  • A controller -> B controller ❌
    같은 계층끼리 사용하는 것: 서로 의존하는 것
    다른 계층끼리 사용하는 것: 독립/모듈화가 잘 되어있는 것
profile
@gari_guri

3개의 댓글

comment-user-thumbnail
2024년 7월 22일

근데요 왜 강형욱: DTO, 박완규: Entity 인가요?
저는 강형욱이 Entity 같은데요?

1개의 답글
comment-user-thumbnail
2024년 7월 22일

근데요 왜 강형욱: DTO, 박완규: Entity 인가요?
저는 강형욱이 Entity 같은데요?

답글 달기