dubiju
쟈근개발자_성장기록
dubiju
전체 방문자
오늘
어제
  • 분류 전체보기
    • Micropython
    • 자료구조&알고리즘
    • 언어
    • CS
    • DB
    • Spring
    • Project
    • 취업
    • TIL
    • etc
    • BE42

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

티스토리

hELLO · Designed By 정상우.
dubiju

쟈근개발자_성장기록

DTO에 대해 알아보자
Spring

DTO에 대해 알아보자

2022. 12. 16. 11:33

DTO (Data Transfer Object)

마틴 파울러(Martin Fowler)가 'Patterns of Enterprise Application Architecture' 라는 책에서 처음 소개한

엔터프라이즈 애플리케이션 아키텍처 패턴의 하나

 

Transfer -> 데이터를 전송하기 위한 용도의 객체

 

데이터 전송은 어떤 구간에서 이루어질까?

 

클라이언트 - 서버 간 데이터 전송

클라이언트 --- 요청 데이터 -----> 서버

클라이언트 <-- 응답 데이터 ----- 서버

 

DTO가 필요한 이유

DTO 클래스를 이용한 코드의 간결성

회원 정보에는 주소, 로그인 패스워드, 패스워드 확인 정보 등 많은 정보들이 있다. 

이 정보들을 모두 @RequestParam 애너테이션으로 사용하게 되면 파라미터로 추가 되는 @RequestParam 개수가 계속 늘어나게 될 것이다. 

 

이런 경우, 클라이언트의 요청 데이터를 하나의 객체로 모두 전달 받을 수 있다면 코드 자체가 간결해 질 것이다. 

 

예제 코드 

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(@RequestParam("email") String email,
                                     @RequestParam("name") String name,
                                     @RequestParam("phone") String phone) {
        Map<String, String> map = new HashMap<>();
        map.put("email", email);
        map.put("name", name);
        map.put("phone", phone);

        return new ResponseEntity<Map>(map, HttpStatus.CREATED);
    }

		...
		...
}

회원 정보를 전달 받기 위해 DTO 클래스를 적용한 경우

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(MemberDto memberDto) {
        return new ResponseEntity<MemberDto>(memberDto, HttpStatus.CREATED);
    }

		...
		...
}
  • @RequestParam 을 사용하는 부분이 사라지고 MemverDto memberDto가 추가되었다. 
  • @RequestParam 을 통해 전달 받은 요청 데이터들을 Map에 추가하는 로직이 사라지고, MemberDto 객체를 ResponseEntity 클래스의 생성자 파라미터로 전달하도록 변경되었다. 

데이터 유효성(Validation) 검증의 단순화

유효성 검증이란 '서버쪽에서 유효한 데이터를 전달 받기 위해 데이터를 검증하는 것'을 말한다. 

 

HTTP 요청을 전달 받는 핸들러 메서드는 요청을 전달 받는 것이 주 목적이기 때문에 최대한 간결하게 작성되는 것이 좋다. 

 

핸들러 메서드 내부에 있는 유효성 검사 로직을 외부로 뺄 수 있다면 핸들러 메서드의 간결함을 유지할 수 있을 것이다.

 

DTO 클래스를 사용하면 유효성 검증 로직을 DTO 클래스로 빼내어 핸들러 메서드의 간결함을 유지할 수 있다. 

 

@Vaild 애너테이션은 유효성 검증을 적용하게 해주는 애너테이션이다.

 

DTO의 사용 목적

  • 비용이 많이 드는 작업인 HTTP 요청의 수를 줄이기 위함
  • 도메인 객체와의 분리 

 

DTO 클래스를 만들 때, 주의해야 할 점

- 멤버 변수 이외에 각 멤버 변수에 해당하는 getter  메서드가 있어야 한다

getter 메서드가 없다면 Response Body에 해당 멤버 변수의 값이 포함되지 않는 문제가 발생할 수 있다.

setter 메서드는 필수 항목은 아니다.

 

Java base 개발을 진행하다보면 getter / setter 메서드를 작성해야 되는 경우가 상당히 빈번하다.

이 경우, 개발자가 일일이 getter / setter 메서드를 작성하는 것은 비효율적인 측면이 있기 때문에

Intellij IDE에서 지원하는 Generate Code 기능을 사용하자

 

- Intellij Generate Code 기능 사용법: https://www.jetbrains.com/idea/guide/tips/generate-getters-and-setters/

 

Generate constructors and accessor methods - IntelliJ IDEA Guide

You can use ⌘N (macOS), or Alt+Insert (Windows/Linux) for the Generate menu and then select Constructor, Getter, Setter or Getter and Setter.

www.jetbrains.com

현업에서는 lombok  이라는 라이브러리를 이용해 getter / setter 메서드를 내부에서 자동으로 만들어 사용한다고 한다.

 

DTO 유효성 검증이 필요한 이유 

일반적으로 Frontend 쪽 웹 사이트에서는 JS를 이용해 사용자가 입력하는 입력 폼 필드의 값에 대해 1차적으로 유효성 검증을 진행한다.

 

Frontend 쪽에서 유효성 검증을 하는데 굳이 Backend 애플리케이션 쪽에서 유효성 검증을 할 필요가 있나 싶지만 Frontend 쪽에서 유효성 검사에 통과되었다고 그 값이 반드시 유요한 값이라고 보장할 수 없다.

 

JS로 전송되는 데이터는 브라우저의 개발자 도구를 사용해서 BreakPoint를 추가한 뒤에 얼마든지 그 값을 조작할 수 있기 때문에 Frontend 쪽에서 유효성 검사를 진행했다고 하더라고 서버 쪽에서 한번 더 유효성 검사를 진행해야 한다.

 

Frontend 쪽에서 진행하는 유효성 검사는 사용자 편의성 때문에 진행한다 생각하자

 

유효성 검증

  • email
    • @NotBlank
      • 이메일 정보가 비어있지 않은지 검증
      • null 값이나 공백, 스페이스 같은 값들을 모두 허용하지 않는다.
      • 유효성 검증에 실패하면 에러 메시지가 콘솔에 출력된다.
    • @Email
      • 유효한 이메일 주소인지 검증
      • 유효성 검증에 실패하면 내장된 디폴드 에러 메시지가 콘솔에 출력된다.

💡 kevin1111@abcd와 같이 gmail.com 같은 이메일 주소 형식이 아닌데도 유효성 검증에 통과하는 이유

gmail.com과 같은 이메일 주소에서 gmial.com 은 도메인 네임(Domain Name)을 의미
그 중에서 .com은 최상위 도메인(TLD, Top-Level Domain)을 의미하는데 이메일 주소의 스펙(사양, Specification)을 확인해보면 최상위 도메인이 없는 이메일 주소의 경우도 때로는 정상 이메일 주소로 허용을 하는 것을 확인할 수 있다.

따라서 만약 현실적으로 최상위 도메인까지 포함되어야 유효한 이메일 주소라고 판단하고 싶은 경우에는 정규 표현식을 이용해 조금 더 세밀한 유효성 검사 조건을 지정할 수 있다.
  • name
    • @NotBlank
      • 이름 정보가 비어있지 않은지를 검증
      • null 값이나 공백, 스페이스 같은 값들을 모두 허용하지 않는다. 
      • 유효성 검증에 실패하면 @NotBlank 의 message 애트리뷰트에 지정한 문자열이 에러 메시지로 콘솔에 출력된다.
  • phone
    • @Pattern
      • 휴대폰 정보가 정규표현식(Regular Expression)에 매치되는 유효한 번호인지 검증
      • 유효성 검사에 실패하면 내장된 디폴트 에러 메시지가 콘솔에 출력된다. 

정규 표현식(Regular Expression)

name 멤버 변수에 사용한 “^\\S+(\\s?\\S+)*$” 정규 표현식에서
‘^’은 문자열의 시작을 의미합니다.‘$’는 문자열의 끝을 의미합니다.
‘*’는 ‘*’ 앞에 평가할 대상이 0개 또는 1개 이상인지를 평가합니다.
‘\s’는 공백 문자열을 의미합니다.
‘\S’ 공백 문자열이 아닌 나머지 문자열을 의미합니다.
‘?’는 ‘?’ 앞에 평가할 대상이 0개 또는 1개인지를 의미합니다.
‘+’는 ‘+’ 앞에 평가할 대상이 1개인지를 의미합니다.

“^\\S+(\\s?\\S+)*$”를 정규 표현식으로 추가하면 아래 예시의 문자열은 유효성 검증에 실패합니다.

유효성 검증 실패 예)
”” → 공백 문자만 있으므로 검증 실패
” 홍길동” → 시작 문자가 공백이므로 검증 실패
”홍길동 “ → 끝 문자가 공백이므로 검증 실패
“홍 길동” → 문자와 문자 사이의 공백이 1개를 초과하므로 검증 실패

더보기
  • 프런트엔드 쪽에서 유효성 검증을 진행했다 하더라도 서버 쪽에서 추가적으로 유효성 검증을 반드시 진행해야 한다.
  • 프런트엔드 쪽에서의 유효성 검증 프로세스는 사용자 편의성 측면에서 필요한 작업이다.
  • Jakarta Bean Validation의 애너테이션을 이용하면 Controller 로직에서 유효성 검증 로직을 분리할 수 있다.
  • Jakarta Bean Validation은 애너테이션 기반 유효성 검증을 위한 표준 스펙이다.
  • Hibernate Validator는 Jakarta Bean Validation 스펙을 구현한 구현체이다.
  • Spring에서 지원하는 @Validated 애너테이션을 사용하면 쿼리 파라미터(Query Parameter 또는 Query String) 및 @Pathvariable에 대한 유효성 검증을 진행할 수 있다.
  • Jakarta Bean Validation에서 빌트인(Built-in)으로 지원하지 않는 애너테이션은 Custom Validator를 통해 Custom Annotation을 구현한 후, 적용할 수 있다.

 

  • 정규 표현식에 대해서 더 알아보고 싶다면 아래 링크를 확인하세요. 정규 표현식은 프로그래밍 언어에 종속되지 않은 표현식입니다. 따라서 아래 관련 자료에서 Java와 관련된 자료가 아니어도 정규 표현식을 학습하는데 지장이 없으니 이 점 참고해서 관련 자료를 살펴보기 바랍니다.
    • 정규 표현식 관련 자료
      • https://www.w3schools.com/java/java_regex.asp
      • https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions
    • 정규 표현식 모범 사례 자료
      • https://docs.microsoft.com/ko-kr/dotnet/standard/base-types/best-practices
  • Jakarta Bean Validation에 대해서 더 알아보고 싶다면 아래 링크를 확인하세요.
    • Jakarta Bean Validation Specification
      • https://beanvalidation.org/2.0/spec/
    • Jakarta Bean Validation Built-in Constraint definitions
      • https://beanvalidation.org/2.0/spec/#builtinconstraints
    • Hibernate Validator
      • https://docs.jboss.org/hibernate/validator/6.2/reference/en-US/html_single/#preface
  • Java Bean에 대해서 더 알아보고 싶다면 아래 링크를 확인하세요.
    • Java Bean 관련 자료
      • https://ko.wikipedia.org/wiki/자바빈즈
  • 이메일 주소의 스펙에 대해서 더 알아보고 싶다면 아래 링크를 참고하세요.
    • https://en.wikipedia.org/wiki/Email_address

'Spring' 카테고리의 다른 글

DDD(Domain Driven Design)  (0) 2022.12.23
JDBC 기반 데이터 액세스 계층  (0) 2022.12.23
Spring MVC란?  (0) 2022.12.15
[Spring의 특징] 5. PSA  (0) 2022.12.13
[Spring의 특징] 2. IoC  (0) 2022.12.09
    'Spring' 카테고리의 다른 글
    • DDD(Domain Driven Design)
    • JDBC 기반 데이터 액세스 계층
    • Spring MVC란?
    • [Spring의 특징] 5. PSA
    dubiju
    dubiju

    티스토리툴바