본문 바로가기

Programing/Framework

(52)
[JPA] @Converter 는 어떻게 동작할까? 지니님이 기본 데이터 타입과 String 등을 enum 으로 바꾸는 작업을 진행하셨다. 대부분은 아래와 같이 @Enumerated 으로 enum의 이름을 사용하도록 작업을 했다. import lombok.Getter; import lombok.Setter; import javax.persistence.*; @Entity @Table(name = "TEST") @Getter @Setter public class TestEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "SEQ") private Integer id; @Column(name = "ACTION_TYPE", length = 100) @Enumerated(..
[스프링] 생성자가 private 일때 스프링은 객체는 어떻게 만들까? 어제 지니님의 요청한 코드리뷰를 하다 아래와 같은 코드를 발견했다. (이름은 적절히 각색하였습니다.) import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @NoArgsConstructor(access = AccessLevel.PRIVATE) class ReceiptProperties { private String receiptUrl; } 내가 하려는 이야기는 lombok을 썼다는 것이 아니고 왜 private 생성자로 결정 했을까가 포인트이다. 위의 코드를 일반 자바코드로 풀어쓰면 아래와 같다. class ReceiptProperties { p..
[Spring] FieldError의 계층구조 스프링 Controller에서 파라미터 에러가 나면 BindingResult 로 바인딩 결과를 받아 올 수 있다. @RestController @RequestMapping(value = "/some") public class SomeController { @PostMapping(value = "/thing") public ResponseDto ready(@RequestBody @Valid Params params, BindingResult bindingResult) { if (bindingResult.hasErrors()) { // ... } 만약에 결과를 받지 않을 경우 @Valid에서 실패한 것은 MethodArgumentNotValidException 예외가 던져진다. 이 예외 안에는 위의 Cont..
[JPA] H2 테스트 코드에서 createdAt 필드가 없던 이유 코드리뷰에서 save 를 반복하며 직접 iteration을 도는 것보다 saveAll 을 호출하는 것이 성능상 더 좋을 것 같다는 comment가 달렸다. 정말로 그럴지 테스트 해보기 위해 테스트코드를 짰다. 사실 테스트라기 보다는 리스트로 데이터를 saveAll을 수행시 어떻게 동작하는지 디버깅을 해보려는 것이었다. @DataJpaTest @ActiveProfiles("test") class RequestRepositoryFunctionalSpec extends Specification { @Autowired RequestRepository sut def "saveAll 로 처리하면 성능상 이점이 있을것이다 by yh"() { given: List entities = [ getDummyEntityWit..
[JPA] N+1 문제 면접 때 자주 나오는 단골 문제 N+1 Ploblem이다. 내가 맡고 있는 팀은 그동안 테이블을 비정규화 해서 사용을 하고 있었기에 엔티티가 관계를 맺고 있지 않아서 이 문제를 만날 일이 없었다. 이번에 현금영수증 관련 기능을 개발하면서 그동안 중복저장하던 데이터를 좀 효율적으로 사용하기 위해 정규화를 해서 테이블을 쪼갰다. 드디어 N+1 문제를 만났다. EntityA, EntityB 가 있는데 EntityB 안에 EntityA를 포함하고 있다고 치자. FetchType이 EAGER 라면 EntityB를 조회하면 자동으로 EntityA 를 조회하는 쿼리까지 수행이된다. 조회하는 EntityB의 개수가 10개라면 각각 관련된 EntityA까지 추가로 +10회 조회가 되어 총 11회의 조회가 발생한다. 그렇..
[Spring JPA] 멀티컬럼 - 쿼리메소드 vs @Query 도비님이 코드리뷰 PR을 주셨다. 기존에 query method로만 사용을 했는데 @Query 를 사용하여 왜 그랬는지 궁금했다. 알고보니 특정 컬럼에 대하여 or 조건으로 결합이 되었던 것이 이유였다. 예를 들어 (t.a = 'abc' or t.a = 'bcd') and ... 같이 우선적으로 적용해야 하는 or가 있는 경우였다. 물론 결합법칙으로 (A OR B) AND C 를 A AND C OR B AND C 로 풀 수는 있지만 trade-off 비용이 더 안좋았을 거라 생각이든다. 다른 생각 하지만 JPA 객체지향이 아닌 쿼리지향으로 사용하고 있지 않는가 하는 생각을 하게 되었다. query method가 점점 길어지고 복잡해지고 있다면 쿼리지향을 하고 있는가 생각해 보는 점검의 시간(냄새)으로 생..
[Spring] spring-retry 재시도 및 백오프 정책 정리 재시도에 대한 생각을 할 때 일반적으로 참고를 할 수 있을 것 같아서 정리했다. 현재 사용하고 있는 spring-retry 1.2.5 기준이다. RetryPolicy (재시도 정책) SimpleRetryPolicy 주어진 횟수만큼만 반복 수행 AlwaysRetryPolicy 항상 재시도를 수행 - 테스트 용도나 수동 설정시 이용 NeverRetryPolicy 1회만 수행(재시도를 안함) - 테스트 용도나 수동 설정시 이용 CircuitBreakerRetryPolicy 서킷 브레이커 방식의 재시도 - 시스템 장애시 유용 ExceptionClassifierRetryPolicy 최종 예외 클래스에 기반한 재수행 TimeoutRetryPolicy 제한을 시간을 가지고 반복을 수행 ExpressionRetryPo..
[spring boot] 2.1.6 -> 2.2.0 테스트 깨짐(인코딩) 무엇이 바뀌었길래 테스트가 깨지는가? org.springframework.test.web.servlet.MockMvc 를 이용한 Mock 컨트롤러 테스트. 한글 인코딩이 깨진다. MockMvc의 경우 perform이 수행되면 MockFilterChain -> HttpServlet -> TestDisplacherServlet -> FrameworkServlet -> HttpServlet - FrameworkServlet -> DispatcherServlet -> AbstractHandlerMethodAdapter ... 등을 거치다. application/json의경우 HttpEntityMethodProcessor 의 handleReturnValue에서 AbstractMessageConverterMetho..