(특강) DTO, Controller, Annotation

Thomas·2023년 7월 25일
0

이번 특강은 최현웅튜터님이 강의 해주신 영상을 토대로 작성을 하였습니다.

간단한 용어

Entity: DB에 있는것들을 객체로 변환을 위한 클래스 정보 (하나! DB랑 매핑)

DTO: 하나의 endPoint(API URL)이 들어오면 알맞는 응답값을 담아서 주는 것!
-> Entity에서 원하는 요청들이 있을텐데
예를 들어 목록을 불러 온다거나 등록을 한다거나 이외의 기능들 마다 DTO가 따로 나와줘야 한다.

그래서 DTO는 용청에 대한 응답의 데이터를 담아서 전달한다.

즉, MVC에서 Model쪽이 될수있다.

Model
- 요청에 대한 응답 데이터로써, View에 출력할 데이터이다. COntroller가 View에 필요한 데이터를 해당 Model에 모두 담아서 주기 떄문에 View의 입장에서는 비즈니스 로직을 몰라도 된다.

View
- Model에 존재하는 데이터를 이용하여 화면을 렌더링한다. HTML 생성 부분

Interceptor
Controller에서 비즈니스 로직을 수행하기 전에 치환 추가과정들을 진행 한다.
예를 들면 request Header 값을 어떻게 추출해서 해쉬맵 같은거에 담아 준다거나 (헤더 영역에서 어떻게 꺼내와서 컨트롤러 영역에서 쓰기 좋게 만들어 주는 역할 )

  • 디스패처 서블릿에서 컨트롤러로 넘기기 전에 처리해야 하는 기능을 처리하는 컴포넌트
  • 헤더 영역의 특정 데이터를 추출하는 등의 컨트롤러가 비즈니스 로직을 처리하기 전, 사전 준비를 담당하는 컴포넌트.

도메인

Domain: 해결하고자 하는 문제의 영역
예를 들면 쇼핑몰 프로젝트이면, 게시글,댓글,결제,정산등을 도메인이라고 할 수 있다.

프로젝트를 하다보면 도메인을 나누지 않았을 경우 코드가 많이 난잡해 진다. 그래서 도메인 단위로 패키지를 나눠주는게 좋다.

여기선 다른 도메인들은 우리가 흔히 아는 도메인이라고 보시면 되는데 common은 나누기 애매한 것들을 넣어주면 된다.


예외처리라든지 jwt등등을 넣어주면 된다.

JWT는 .기준으로 나눠진다

예를 들면

Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIyOTI0MzkyMjgyIiwiYXV0aCI6IlVTRVIiLCJleHAiOjE2OTAxMDgzNjEsImlhdCI6MTY5MDEwNDc2MX0.5KOeEXAXspi8PNo6CD3k2_bLH75Z8DkzIhnfZit-W1o

여기 코드에서 . 기준으로 나누게 되면

  1. eyJhbGciOiJIUzI1NiJ9
  2. eyJzdWIiOiIyOTI0MzkyMjgyIiwiYXV0aCI6IlVTRVIiLCJleHAiOjE2OTAxMDgzNjEsImlhdCI6MTY5MDEwNDc2MX0
  3. 5KOeEXAXspi8PNo6CD3k2_bLH75Z8DkzIhnfZit-W1o

이렇게 세개가 나눠지게 되는데

첫번째는 Header 두번째는 payload 세번쨰는 signature → 시크릿 키(HS256)으로 암호화 된 코드

아래의 사이트를 이용해서 3개의 섹션을 볼 수 있다!

https://www.base64decode.org/

→ 게시글/댓글 올릴 떄 굳이 username을 request body에 username을 안 써도 저장이 되는 이유가 사용자를 검증 할 때 jwt Token에 있는 payload에 sub영역을 꺼내서 유저를 저장

Annotation

@AllArgsConstructor는 위험해서 현업에서 잘 쓰지 않는다

→ 순서가 꼬이는 순간 Runtime 에러가 발생한다… 아래에서 자세히 다뤄보겠다

@Builder

내가 넣을 값들을 하나하나 넣어준다.

보통 생성자 위에 @Builder를 넣어주는데 생성자 순서가 다를 수 있기 떄문이다.

그래서 실제로 DTO에 값을 넣어줄 떄도

이렇게 넣어줘도 잘 들어간다.

Lombok 사용상 주의점

@AllArgsConstructor 추가로 @RequireArgsConstructor도 잘 사용하지 말라고 한다.

저 두개의 어노테이션은 매우 편리하게 생성자를 만들어주지만 반대로 치명적 버그가 되게 만들 수도 있다.

@AllArgsConstructor
public static class Password{
    private String currentPassword;
    private String changedPassword;
}
 
Password password = new Password("1234", "2345");

위 클래스에 대해 자동으로 currentPassword, changedPassword순서로 인자를 받는 생성자가 만들어진다. 그런데 저 두개의 순서를 바꾼 경우 IDE가 제공해주는 리팩토링은 전혀 작동하지 않고, lombok이 개발자도 인식하지 못하는 사이에 생성자의 파라미터 순서를 필드 선언 순서에 맞춰 changedPassword, currentPassword로 바꿔버린다. 거기다 이 두 필드는 동일한 Type 이라서 기존 생성자호출 코드에서는 인자 순서를 변경하지 않았음에도 어떠한 오류도 발생하지 않는다.

그래서 아무런 에러없이 잘 작동하는 듯 보이지만 실제로 입력된 값은 바뀌어 들어가게 된다.

→ @RequireArgsConstructor 또한 같은 문제가 존재한다.

대신에 생성자를 (IDE 자동생성등으로) 직접 만들고 필요할 경우에는 직접 만든 생성자에 @Builder 어노테이션을 붙이는 것을 권장한다. 파라미터 순서가 아닌 이름으로 값을 설정하기 떄문에 리팩토링에 유연하게 대응할 수 있다.

public static class Password {
	private String currentPassword;
	private String changedPassword;
	
	@Builder
	private Password(String currentPassword, String changedPassword) {
		this.currentPassword = currentPassword;
		this.changedPassword = changedPassword;
	}
}

// 필드 순서를 변경해도 문제가 없다.
Password password = Password.builder().currentPassword("1234").changedPassword("2345").build();

필드에 붙은 어노테이션이 생성자 쪽으로 전달 안 된다

  • 필드에 어노테이션이 있을 경우 자동으로 생성자로 전달이 안 되어 문제가 될 수 있다.

무분별한 @EqualsAndHashCode 사용 자제

@Data 사용금지

@Value 사용금지

위에 껏들 보고 싶으면 아래 출처로 보자!

출처: https://kwonnam.pe.kr/wiki/java/lombok/pitfall

profile
Backend Programmer

1개의 댓글

comment-user-thumbnail
2023년 7월 25일

이런 유용한 정보를 나눠주셔서 감사합니다.

답글 달기