전체 글

프로그래밍 언어/Java + Kotlin

[Kotlin] 특정 프로퍼티 Json 직렬화/역직렬화 시 제외시키기

data class로 레디스에 객체를 역직렬화하는 과정에서 다음과 같은 에러가 발생했다. 에러 내용은 ttl이라는 필드가 non-nullable인데, 실제로는 null이 들어가서객체 생성에 실패했다는 것이다. Could not read JSON: Instantiation of [simple type, class ...] value failed for JSON property ttl due to missing (therefore NULL) value for creator parameter ttl which is a non-nullable type class는 대략 다음과 같은 형태였다. 분명 @JsonIgnore 애너테이션으로 직렬화/역직렬화에서 해당 프로퍼티를 제외했는데, 왜 직렬화/역직렬화에 포함된 ..

JPA

[JPA] 실무에서 만난 N+1 문제 해결하기 (feat. LazyInitializationException)

1. 개요 운영 과정에서 프론트에서 쿠폰 관련 API 호출 시 간헐적으로 타임아웃이 발생한다는 리포트가 들어왔다. APM을 통해 좀 더 면밀히 살펴보니 오라클 쿼리가 비정상적으로 많이 발생하고 있음을 확인할 수 있었다. 발급된 쿠폰을 조회하는 과정에서 N+1 문제와 leftjoin의 잘못된 사용으로 인한 데이터 뻥튀기가 발생하면서 쿠폰 정책에 대한 조회가 불필요하게 이뤄진 게 화근이었다. 데이터 뻥튀기가 되는 문제는 원인이 분명했지만, N+1 문제는 의아했다. 분명 Lazy Loading을 걸어놨는데, 왠지 모르게 Eager Loading이 발생했다. 물론 Lazy Loading을 건다고 해서 N+1 문제가 모두 해결되는 것은 아니지만, 적어도 쿠폰 정책을 참조하지 않는 경우엔 N+1이 발생하지 않았어야..

책/도메인 주도 설계 첫걸음

[도메인 주도 설계 첫걸음] Part 4. 다른 방법론 및 패턴과의 관계

본문은 도메인 주도 설계 첫걸음을 읽고 간단하게 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다. 14장) 마이크로서비스 마이크로서비스 의미 서비스의 의미 미리 정의된 인터페이스를 사용해 하나 이상의 역량에 접근하기 위한 메커니즘 (OASIS) 미리 정의된 인터페이란 서비스로부터 데이터를 넣고 빼는 모든 메커니즘을 의미한다 마이크로서비스의 의미 마이크로 퍼블릭 인터페이스에 의해 정의된 서비스 장점 단일 서비스의 기능과 연동되는 다른 시스템 구성요소 모두를 쉽게 이해할 수 있음 유지/보수/확장이 쉬워짐 구성 인터페이스가 적고, 구현 복잡성이 높은 깊은 모듈로 구성하라 즉, 외부에 노출되는 기능은 적게 하고 구현 복잡성은 높여라 마이크로서비스와 바운디드 컨..

책/도메인 주도 설계 첫걸음

[도메인 주도 설계 첫걸음] Part 3. 도메인 주도 설계 적용 실무

본문은 도메인 주도 설계 첫걸음을 읽고 간단하게 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다. 10장) 휴리스틱 설계바운디드 컨텍스트작은 바운디드 컨텍스트를 만드려는 목적으로 기능을 줄이는 방향으로 모델링하는 것보다는 그 반대로 하는 것이 낫다. 즉, 모델의 기능이 포함하는 크기 그대로 바운디드 컨텍스트를 다루는 것이 낫다.바운디드 컨텍스트를 너무 작게 설정하여 그 경계를 리팩토링하는 것은 비용이 많이 들고, 대부분의 경우 기술 부채로 남게 된다 (물리적 경계)반면 넓은 바운디드 컨텍스트의 경계 또는 여러 하위 도메인에 걸친 경계는 보다 안전하다 (논리적 경계)따라서 초기에 바운디드 컨텍스트를 설계할 때는 경계를 넓게 설정하고, 추후 도메인이 쌓이게..

책/Effective Kotlin

[이펙티브 코틀린] 아이템 50: 컬렉션 처리 단계 수를 제한하라

본문은 Effective Kotlin을 읽고 간단하게 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다. 컬렉션 처리 메서드는 각각의 단계에서 추가적인 컬렉션을 만들어낸다. 시퀀스로 처리한다 하더라도 추가적인 객체를 만들어낸다. 따라서 적절한 메서드를 사용해서 컬렉션 처리 단계 수를 적절하게 제한하는 게 좋다. // Soso fun List.getNames(): List = this .map { it.name } .filter { it != null } .map { it!! } // Better fun List.getNames(): List = this .map { it.name } .filterNotNull() // Best fun List.getNam..

코택
TaxFree