콘텐츠로 이동

2021 05 07

2021-05-07

DTO Validation, DTO 변환

  • 참고: https://github.com/HomoEfficio/dev-tips/blob/master/DTO%EC%99%80%20Bean%20Validation.md
  • 참고: https://github.com/HomoEfficio/dev-tips/blob/master/DTO-DomainObject-Converter.md
  • DTO Validation - 클라이언트의 정보는 DTO로 담겨 서버로 넘어오게 됨 - DTO에 반드시 넘겨자야 할 필수 정보 누락되면 오류가 발생... - 클라이언트 잘못인지, 서버 잘못인지 판단해야함 - 논리적으로 보면 필요한 정보를 똑바로 안넘겨준 클라이언트 잘못 - 4xx 에러를 뱉어줘야 함 - @NotNull을 사용하여 필요한 정보 안들어왔다면 에러를 처리하도록 하자 - @Valid를 사용하여 넘어온 DTO 검증하도록 하자
    import javax.validation.constraints.NotNull;
    public class ProductDto {
    
        @NotNull
        private String productCode;
    
        ...
    }
    
    @Controller
    public class ProductController {
        @RequestMapping(value = "/whatever", method = RequestMethod.POST)
        public void saveProduct(@Valid ProductDto productDto, BindingResult bindingResult) throws BindException {
            if (bindingResult.hasErrors()) {
                throw new BindException(bindingResult);
            }
        }
    }
    
  • DTO-Domain 변환 위치 - 프론트엔드의 View에는 DTO가 전달되고, 백엔드의 데이터 저장소에는 결국 Domain 객체가 필요 - 중간 어디선가 변환해주는 지점이 필요! - 서비스에서 변환해주는 것이 타당하다 - Domain -> DTO는... DTO에 들어갈 정보를 Domain이 충분히 알고 있어서 변환 쉬움 - DTO -> Domain은... 가령 id 값 만으로 Domain 생성 불가! Repository 조회 하던가 해야함! - 따라서 변환 로직은 서비스에서 책임을 갖는 것이 좋음 - 컨트롤러에서 도메인 객체 구성할 능력이 없음

브라운 수업

  • 테스트 - 테스트는 상호 독립적으로 작성하기 - 테스트가 서로 영향을 주면 안대! - "강남역" 여기저기서 쓰면 테스트 깨짐 - 테스트간 공유되는 자원들을 신경써서 테스트하자! - Spring Beans - Database - AfterEach, BeforeEach - Spring Boot 안내려가면 자동 RollBack X - DirtiesContext? - Context를 재사용 못하도록 한다 - 매 테스트 메서드 마다 기존의 Context를 파토내서 새로 로드하게끔 - 매 테스트 마다 새로운 빈들이 로드가 됨 - Context 내의 빈들을 새로 만들어서 사용 - 찾아보기 - @Transactional - rollback 설정 Yes - 공식 문서 보기 - TransactionalTestExecutionListener 동작 - 기본적으로 Rollback true - @Rollback(false)를 통해 롤백 안되는 설정 부여 가능 - 프록시 객체에서 Transaction 처리 - @Sql("/truncate.sql") - @DirtiesContext(classMode = BEFORE_EACH) - 롤백보다는 빈 새로 생성 - 테스트 비용 BIG - 메서드 전에 재생성, 클래스 전에 재생성 설정 가능 - 현구막: @DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD) 사용하니까 다른 테스트 클래스에서 테스트가 종료된 후에 찌꺼기 값이 다음 테스트 클래스까지 넘어왔어요 - @PropertySource - application.yml - jwt-token
  • 테스트 비용 - 테스트 코드를 동작시켜 빠르게 피드백 받기 - 근데 테스트 하나당 몇초 걸리면 안되자나 - 테스트 가독성 올리기 - 테스트의 목적에 집중하자! - 통합 E2E 시스템 테스트 - 어떤 테스트 만들까? << 어떤 목적을 가지고 테스트를 하는 것일까?? - 통합테스트와 E2E 목적의 차이 - 통합테스트: 독립된 단위가 맞물려 똑바로 돌아가는 것 확인 - 넓은 의미: "전체 기능"이 잘 동작하는지 - 좁은 의미: 애초에 정의한 기능이 "맞물리는 부분"이 잘 동작하는지
  • @DirtiesContext - 참고: https://shortstories.gitbooks.io/studybook/content/dirtiescontext.html - 스프링 테스트에서 애플리케이션 컨텍스트는 딱 한 개만 만들어지고 모든 테스트에서 공유 - 기존의 Context를 재활용하는 방식! - 원칙적으로는 애플리케이션 컨텍스트 구성/상태를 테스트에서 변경하면 X - 앞선 테스트에서 특정 Bean의 속성값 바뀌면, 다음 테스트 실패할 수도! - @DirtiesContext를 통해서 해결 가능 - 테스트의 테스트 케이스 마다, 테스트 수행 전/수행 후 context 다시 생성하도록 지시할 수 있음 - 사용법 - 메서드/클래스 레벨에 어노테이션을 붙여 동작하자!(methodMode, classMode) - 클래스의 테스트 시작 전 Context 재생성 - @DirtiesContext(classMode = BEFORE_CLASS) - 클래스의 테스트 모두 끝난 다음 Context 재생성 - @DirtiesContext - 클래스의 모든 테스트 케이스마다 시작하기 이전에 Context 재생성 - @DirtiesContex(classMode = BEFORE_EACH_TEST_METHOD) - 클래스의 모든 테스트 케이스 끝날 때 마다 Context 재생성 - @DirtiesContext(classMode = AFTER_EACH_TEST_METHOD) - 특정 케이스 시작하기 전에 Context 재생성 - @DirtiesContext(methodMode = BEFORE_METHOD) - 특정 케이스 시작한 이후 Context 재생성 - @DirtiesContext
  • @Transactional - 참고: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html - 트랜잭션 속성을 개별 메서드나 클래스에 추가 - 클래스 레벨에서 해당 어노테이션을 붙이면, 해당 클래스와 하위 클래스의 모든 메서드에 기본적으로 해당 어노테이션 추가된 효과 발생 - 다만 조상한테는 적용X - 만약 커스텀 롤백이 적용되지 않는 다면, 트랜잭션은 RuntimeException과 Error에 대해 롤백 될 것 - 어노테이션은 보통 thread-bound transactions에서 동작함 - 현재 실행중인 쓰레드에 대해 data access operation을 제어 - 해당 어노테이션은 메서드 내에서 새로이 시작된 쓰레드에 대해 동작을 전파하지 않음!
  • jwt-token? - 참고: https://www.youtube.com/watch?v=zC5dLbZMAW0 - 세션으로 로그인 상태 관리했었음 - 각각의 서버가 다른 서비스를 제공해주는 경우도 있었음 - 세션을 공유하는게 매우 복잡했음 - Client --(ID/password)--> Server - Client <--(Token)-- Server - 오직 Request 내의 Token 만 보고 권한을 줌 - Encoded & Decoded - Header: 어떤 토큰 종류인지, 어떤 알고리즘으로 생성할 건지 - Payload: 어떤 데이터를 토큰에 담을 것인지 - Signature: 보안에 중요한 부분!!!! 서버에서 해시값으로 해당 토큰을 저장해 둠