본문 바로가기

Programing/Framework

(71)
[Spring] Controller & RequestMapping : RequestMappingInfo AbstractAutowireCapableBeanFactory # createBean → doCreateBean → initializeBean → invokeInitMethods → (InitializingBean) afterPropertiesSet RequestMappingHandlerMapping # afterPropertiesSet AbstractHandlerMethodMapping # afterPropertiesSet → initHandlerMethods → processCandidateBean → if (isHandler(beanType)) → detectHandlerMethods → getMappingForMethod RequestMappingHandlerMapping # getMappingF..
[JOOQ] MySQL JDBC batch 벤치마킹 batch 처리에 대한 의견 코드리뷰를 하다 jdbc의 batch 처리를 하면 성능 효과를 얻을 수 있을 것 같다는 성준님의 의견이 있었다. executeBatch 를 이용한 방법입니다. (e.g Batch Processing in JDBC atBaeldung) 단일 DELETE N 건 실행 대비, 성능상 이점이 있습니다. 평소 성준님은 최적화에 대해 M.A.Jackson의 말을 인용하시던 분이었다. 최적화를 할 때는 아래의 두 규칙을 따르라. 규칙1: 하지마라 규칙2: (전문가들만 따를 것) 아직은 하지마라 - 완벽히 명료한, 최적화되지 않은 해답을 얻을 때까지는. - M. A. 잭슨(M. A. Jackson) 사실 네트워크 round-time을 생각해본다면 상식적으로 한번에 batch로 보내는 것이 ..
[Spring MVC] HandlerMethodArgumentResolver 구현하기 가끔 Controller 에 특정 타입의 값을 자동으로 받고 싶을 경우가 있다. path가 "foo/{a}/{b}" 인데 a 랑 b값을 aggregation 해서 특정 객체로 만들고 싶은데 프레임워크에게 시키고 싶은 것이다. 이럴 경우 @PathVariable 에 대한 메서드 인자 Resolver 를 만들어주면 해결이 가능하다. 기본적으로 @PathVariable Resolver는 두 가지가 있다. PathVariableMethodArgumentResolver PathVariableMapMethodArgumentResolver 위의 경우는 파라미터의 이름이나 @PathVariable 에 지정된 value 의 값을 매핑시켜준다. 가끔 타입 변환이 필요한 경우에는 conversionService에게 타입 변..
[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회의 조회가 발생한다. 그렇..