JAVA/Spring Boot 11

[Validation] @Valid 직접 실행하는 법

통상적으로 작성해둔 Validation은 Controller딴에서 ReqeustDto로 역직렬화 할 때 Spring Boot가 자동으로 해준다. 하지만 나는 RequestDto뿐만 아니라 ResposneDto나 내부적으로 사용하는 Class에서도 사용할 수 있게끔 하고 싶었다. Validator를 사용해서 생성자 호출시에 유효성 검사를 하게끔 했다. Exception Advice에서 처리 하던 BindException과 형태가 달라서 문제가 생겼다. 기존의 방식과 똑같이 Exception을 만들기 위한 코드도 함께 첨부한다. BindException 잘못된 변수명과 그 이유에 대한 Message를 함께 출력하는 코드다. 아래 코드는 디버깅을 통해 변수명과 메세지를 찾은 뒤 맵핑시켰다. 관련 포스팅 @Ex..

JAVA/Spring Boot 2023.10.10

Compile(API), Implement 차이점

Compile 은 해당 라이브러리가 의존하고 있는 모든 모듈를 불러오고 Implement는 최소한의 모듈만 불러온다. Implement가 성능상 유리한것이 확실한 만큼 거의 모든 Gradle 설정에 Implement가 사용되고 있다. 다만, 궁금한 점은 결국 Implement 사용시 라이브러리를 구성하는 모든 모듈를 불러오지는 않는다는 건데 애초에 라이브러리가 효율적으로 의존성을 구성한게 아니라는 건지 불러오지 않아도 되는 모듈이 왜 존재하는지 이해가 잘 가지 않아서 찾아봤다. 문제 상황은 다음과 같다. 모듈 A - 모듈 B를 의존하는 라이브러리 X 가 있고 모듈 A - 모듈 C를 의존하는 라이브러리 Y 가 있을때, complie을 사용하면 모듈 A를 중복해서 2번 빌드하게 되고 implement를 사용..

JAVA/Spring Boot 2023.05.14

Annotation) 커스텀 어노테이션으로 Enum 유효성 검사하기

Request에서 String을 받아 Enum으로 변환하는 작업을 해야한다. 받아온 String이 Enum에 속한 값인지 판단하는 Validation Annotation을 생성하고자 한다. 물론 애초에 convertor를 통해 Request에서 직접 Enum타입을 받는 방법도 있다. 다만, 후자의 경우에는 convertor도 구현하고 Enum Validator도 구현해야하기에 비용이 적게드는 첫 번 째 방법을 선택했다. 어노테이션을 만든다는 것은 생각 보다 어렵지 않았다. 무엇보다 Enum Validator는 이미 코드가 많기 때문에 구현에 어려움은 없었는데 문제는 List로 된 Enum은 구글링으로 찾기 어려웠기에 직접 구현했다. Valid에 사용되는 어노테이션은 예시가 많기 때문에 구현에 어려움은 없..

JAVA/Spring Boot 2023.03.13

Join을 Map으로 최적화

기존 이름은 'Join시 n+1 문제 Map으로 해결' 이었으나 생각해보니 n+1 문제가 아니라 그냥 최적화 문제이므로 수정했다. 회사에서 사용중인 DB는 외래키가 존재하지 않고 양이 워낙 많아(테이블만 280개..) JPA를 활용한 batch_fetch_size의 기능을 쓰기 어렵다. 따라서 이를 자료구조로 해결하고자 방향을 잡고 생각해보니 Map을 활용하면 꽤나 효율적으로 작업을 할 수 있을 것 같았다. 부모 spot 테이블과 자식 spotImg, spotTheme 테이블을 예로 들어 설명해보겠다. 일단 spot에서 필요한 데이터만 가지고 온다. (자세한 쿼리는 보안상 생략) List spotListByCondition = spotRepository.getSpotListByCondition(spotI..

JAVA/Spring Boot 2023.02.23

JPA) [수정]@DynamicUpdate, @DynamicInsert

추가... 작업중 이 게시글이 완전히 잘못되었다고 깨달았다. @DynamicUpdate와 ON DUPLICATE KEY UPDATE 는 서로 완전히 상관없다. 만약 중복시 update하는 기능을 사용하고 싶다면 update 로직을 따로 작성해서 select 후 insert나 update를 하거나 native query를 이용해서 업데이트 시키면된다. 전자의 경우 만약 업데이트된 데이터가 없다면 @DynamicUpdate로 인해 쿼리를 날리지 않을것이다. 회사에서 일하던 중 'INSERT ... ON DUPLICATE KEY UPDATE ...' 라는 sql문을 발견했다. PK나 unique key를 기준으로 해당 값이 이미 존재하면 row를 새로 생성하지 않고 업데이트하겠다는 의미다. 더티체킹 이라는 키..

JAVA/Spring Boot 2023.02.07

[Validation] 누락된 값 전역 처리, 클라이언트에 상세히 표시

Validation의 메세지 처리는 생각보다 쉽지않다. 다음과 같이 작성된 Validation message는 서버에서만 확인 가능하다. 하지만 유효성 검사라는 것은 클라이언트에게 보여줘야 의미가 있지 서버에서 확인하는 것은 별로 의미가 없다. @Getter public class SpotStayListReqDto { @NotNull(message = "spotId가 비어 있습니다.") private Integer spotId; @NotEmpty(message = "checkInDate가 비어 있습니다.") @Size(min = 8, max = 8, message = "yyyyMMdd 형식으로 작성 바랍니다.") private String checkInDate; @NotEmpty(message = "ch..

JAVA/Spring Boot 2023.01.25

Spring Boot, Gradle 멀티 모듈 프로젝트 실전 예제

시작하기 전에.. 멀티 모듈 프로젝트란 무엇인가에 대해 아주 자세히 쓰여있다. 개념적인 부분은 아래 링크를 통해 이해하자. 멀티모듈 설계 이야기 with Spring, Gradle | 우아한형제들 기술블로그 {{item.name}} 멀티 모듈 설계 이야기 안녕하세요. 배달의민족 프론트 서버를 개발하고 있는 권용근입니다. 멀티 모듈의 개념을 처음알게 되었을 때부터 현재까지 겪었던 문제점들과 그것을 어떻게 techblog.woowahan.com 멀티 모듈을 설정하는 방법은 꽤나 많지만 부가적인 작업을 최대한 하지 않는 방식으로 설정했다. Gradle 에서 권장하는 최신 방식은 자식 모듈에서 부모 모듈을 명시하게끔 했는데 자식 모듈만 봐서는 이게 뭘하는 코드인지 파악하기 힘들다는 이유다. 하지만 프로젝트를 생..

JAVA/Spring Boot 2022.12.28

JPA) N+1문제

현재는 Where In 절을 사용하는 Batch Fetching 방식을 선호한다. N+1문제는 1:N or N:1 관계에서 발생하는 문제로 1번의 쿼리를 보냈지만 N번의 쿼리가 더 발생하는 문제다. 외래키에 해당하는 하위 엔티티를 하나씩 조회하므로 N번 더 쿼리를 보내게 된다. 해결방법으론 Fetch Join, Entity Graph 두가지가 있다. Fetch Join @Query("select DISTINCT b from Board b join fetch b.likesList") List findAllFetchJoin(); Entity Graph @EntityGraph(attributePaths = {"likesList"}) @Query("select DISTINCT b from Board b") Li..

JAVA/Spring Boot 2022.06.20