Spring Data Envers로 이력 관리 자동화하기
·
spring
데이터의 변경사항마다 이력을 관리하는 것은 반복적이고 지루한 작업이다.이를 해결해 줄 수 있는 강력한 라이브러리인 Envers가 있다. JPA를 사용하는 환경에서는 이력 관리를 손쉽게 자동화할 수 있게 지원하고 있다.이번 글에서는 Spring Data Envers를 실무에 적용하면서 겪었던 경험과 문제 해결 방안을 공유하고자 한다.Spring Data Envers란?소개Hibernate Envers의 확장으로, Spring Data와 통합된 감사 라이브러리데이터 변경 이력을 자동으로 관리하는 기능 제공주요 특징엔터티의 Create, Update, Delete 이력 관리간단한 설정으로 엔티티 버전 관리 활성화이력 조회 API 제공(이전 상태와 비교 가능)기본 아키텍처이력 대상 _AUD 테이블 생성 (엔티티..
데이터 중심 애플리케이션 설계 - 트랜잭션 처리와 분석
·
데이터 중심 애플리케이션 설계
비즈니스 데이터 처리와 OLTP비즈니스 데이터 처리는 주로 상거래(commercial Transaction) 과정에서 이루어진다.이 과정에서 사용자 입력을 기반으로 데이터베이스의 레코드가 삽입되거나 갱신된다.이러한 작업을 수행하는 애플리케이션은 온라인 트랜잭션 처리(Online Transaction Processing, OLTP)라고 한다. OLTP와 OLAP의 차이점데이터 분석에서 사용하는 질의(Query)는 일반적으로 원시 데이터를 그대로 반환하는 것이 아니라, 많은 수의 레코드를 읽고 필요한 일부 컬럼만 활용하여 집계 통계를 계산한다.이러한 분석 작업은 기업의 현재 성과를 측정하거나 미래의 의사결정을 지원하는 보고서(비즈니스 인텔리전스, BI)를 생성하는 데 유용하다이와 같은 분석 작업은 온라인 분..
데이터 중심 애플리케이션 설계 - 저장소와 검색
·
데이터 중심 애플리케이션 설계
간단한 데이터베이스를 생각해보자.set 함수에 키와 값을 요청하면 차곡차곡 저장하고, get 함수에 키를 담아 요청하면 저장된 값을 반환하는 간단한 구조이다. set 10 { "name": "noose" }set 20 { "name": "google" }set 30 { "name": "naver" }10 { "name": "noose" }20 { "name": "google" }30 { "name": "naver" }get 30 # { "name": "naver" }  append-only 방식으로 간단하게 동작하기에 저장 시 큰 문제가 없다.하지만, 특정 키의 값을 찾을 때 첫번째 라인에서 원하는 키가 나올 때 까지 탐색을 하므로 최악의 경우 검색 비용은 O(N)이다.저장되는 레코드가 증가할 때 마다 ..
DDD - 도메인 주도 설계 첫 걸음, 전술적 설계 - 3
·
아키텍처
간단한 비즈니스 로직 개발비즈니스 로직을 작성하는 방식에는 크게 두가지로 나뉜다.트랜잭션 스크립트 방식과, 도메인 모델 패턴 방식이다.트랜잭션 스크립트: 절차지향 스크립트 방식으로 구현한다.도메인 모델 패턴: 도메인 객체(엔티티와 값 객체) 안에 로직을 캡슐화예제를 위해 간단한 요구사항은 만들어봤다.- 테넌트(Tenant)는 사용자(Invitee)에게 초대장을 보낼 수 있다.- 사용자는 초대를 받으면 수락/거절을 선택할 수 있다.- 초대 상태를 변경하는 것은 초대받은자만이 가능하다. 트랜잭션 스크립트 방식먼저 트랜잭션 스크립트 방식을 알아보자@Entityclass Invitation( val tenantId: Long, val inviteeId: Long, val message: Stri..
DDD - 도메인 주도 설계 첫걸음, 전략적 설계 - 2
·
아키텍처
이전 글에서 DDD가 무엇인지 간략히 알아보았다.그중에서도 바운디드 컨텍스트에 대한 개념을 살펴보았는데,이번 글에서는 각 바운디드 컨텍스트 간에 모델을 어떻게 공유하고 상호작용하는지 설명하려고 한다.Contract바운디드 컨텍스트 간에도 상호작용이 필요하며, 이 상호작용 방식을 컨트랙트(contract)라고 부른다.바운디드 컨텍스트 간 상호작용 패턴컨트랙트는 상호작용 방식에 따라 몇 가지 패턴으로 나눌 수 있다. 대표적으로 협력형, 사용자-제공자, 분리형 패턴이 있다.각 패턴은 바운디드 컨텍스트 간의 의존성과 독립성을 어떻게 유지할지를 결정하는 방식에 따라 구분된다.협력형(cooporation) 패턴파트너십 패턴한 팀은 다른 팀에게 API 변경을 알리고 다른 팀은 충돌 없이 받아들인다.양 팀 모두 커뮤니..
DDD - 도메인 주도 설계 첫걸음, 전략적 설계 - 1
·
아키텍처
이 글에서는 내가 지금까지 서적, 외부 강의, 그리고 경험을 통해 이해한 DDD와 이를 실제로 어떻게 적용했는지 공유하고자 한다. 도메인우선 DDD를 이해하기 전에, DDD의 핵심인 '도메인'이 무엇인지 먼저 알아두면 좋다.도메인은 특정 비즈니스 또는 우리가 해결해야 할 문제 영역을 의미한다.예를 들어, 이커머스에서는 '주문', '결제', '상품' 등이 각각 하나의 도메인으로 정의될 수 있다. 위 예시는 간단했지만, DDD에서 말하는 도메인은 더 세부적으로 나타낼 수 있다. 핵심 하위 도메인예를 들어, 쿠팡은 다음날 상품을 받을 수 있는 🚀 로켓 배송 서비스를 통해 다른 이커머스와 차별화를 두고 있다.이러한 차별화된 서비스가 바로 핵심 하위 도메인에 해당한다.이렇게 경쟁 업체와 다르게 수행하고 있는 것..
Kotlin DSL로 테스트 코드와 함께 API 문서화하기
·
spring/테스트
Spring 진영에서 API 문서화에 관심이 있다면 Swagger와 RestDocs를 한번쯤은 사용해봤거나 들어는 봤을 것이다.이번 문서에서는 Swagger, RestDocs 이 두가지의 장점만을 모아 Kotlin DSL로 리팩토링한 과정에 대해서 소개합니다. 커스텀 DSL 미리보기Swagger 라이브러리 문제점Swagger 사용법에 대해 검색해 보면, 컨트롤러나 사용하는 요청DTO, 응답DTO에 애너테이션을 선언하는 방식을 주로 설명하는 것을 확인할 수 있었다.이 방법은 간단하지만, 경험상 몇가지 문제가 있다는 것을 느낄 수 있었다.컨트롤러나 DTO를 봤을 때, 수 많은 애너테이션으로 인해 가독성 저하가 발생한다.수기 작성이다 보니 문서화에 필요한 타입이나 값들이 검증되지 않은 상태로 등록될 수 있다...
Spring Batch Partitioner를 이용한 최적화
·
spring
단일 스레드 방식의 한계점외부 서버 API로부터 데이터를 받아와 DB에 적재를 해야한다고 하자API 서버에 데이터를 요청할 때 모든 데이터가 아닌 page 단위로 요청해야하는 상황이라면 단건씩 요청을 해야한다.만약 페이지 수가 1000개라면, 단일 스레드에서 1000개 페이지에 데이터를 요청하고, 데이터베이스에 적재해야한다.위 작업을 단일 스레드에서 실행하면 모든 작업을 순차적으로 처리하기 때문에 페이지가 많을 수록 대기시간이 오래걸린다. 이를 해결해 줄 수 있는 방법은 Partitioner를 사용하여 멀티 스레드로 처리하는 것이다.구조파티셔너는 Step이 각 스레드에 배정되어 실행될 수 있도록 분배하는 역할이다.구체적인 분배 방법은 Partitioner 인터페이스를 구현하여 정의할 수 있다.방법파티셔너..
Querydsl 대신 Kotlin JDSL을 채택한 이유
·
kotlin
나는 현재 실무에서 코프링에 JPA를 사용하고 있다. CUD 처리는 JpaRepository를 사용해서 처리하고 있고, 간단한 조회 로직은 JpaRepository를 사용하고있다.조회 로직에서 조금이라도 복잡한 쿼리나 동적 쿼리가 필요하다면 널리 알려진 Querydsl을 사용하여 처리하고 있었다.초기 Querydsl을 선택한 이유라면은 JPA Entity를 기반으로 읽기 쉬운 쿼리를 작성할 수 있고, 김영한 선생님 강의에서도 소개할 정도로 풍부한 레퍼런스가 있다는 것이 전부라고해도 무방하다. 그러다 어느순간 유튜브 알고리즘에 의해 Kotlin JDSL 소개 영상을 시청하게 되었다. 시청 이후 엄청난 라이브러리임을 감지하고 PoC를 진행하게 되었다. 내가 봤던 영상들 https://youtu.be/-Kdr..
SpringBoot S3 Presigned URL 적용
·
spring
일반적인 파일 업로드/다운로드 방식우리 서비스는 파일을 업로드할 때 API 서버를 거쳐 S3에 저장된다.파일 다운로드도 마찬가지로 다운로드 요청을 받으면 S3로 부터 파일을 가져오고 서버에서 파일을 스트림으로 응답한다.이렇게 API 서버를 거치는 방식은 파일을 API 서버가 직접 처리할 수 있다는 것이다. 직접 처리할 수 있다는 의미는 특정 저장소에 직접 접근하여 저장할 수 있고, 바이너리 파일 검사(파일 포맷, 사이즈 등등), 인코딩 같은 전처리 작업을 수행할 수 있다는 것을 뜻한다.장점이 있듯이 단점도 존재하는데, 파일 처리를 직접 하므로 API 서버 자원을 그만큼 사용한다.문제 상황 Pinpoint APM 모니터링 중 CPU가 한번씩 튀는 현상을 발견했다.CPU가 튀는 시점을 종합했을 때 거의 대부..
noose
noose