일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 딥러닝
- 네트워크
- persistance context
- cartograhper
- 포인트클라우드
- Database
- Spring Batch
- Python
- 자율주행
- 프로그래머스
- JPA
- 논문리뷰
- 알고리즘
- 이펙티브자바
- 자료구조
- MySQL
- DeepLearning
- 배달로봇
- 장애물인식
- 아두이노
- 논문
- 자바
- Jetson
- 운영체제
- Java
- Hibernate
- 자바ORM표준JPA프로그래밍
- 디자인패턴
- 영속성컨텍스트
- 파이썬
- Today
- Total
목록전체 글 (56)
제리 devlog
들어가며 배치를 돌리다 보면 실행 시간이 오래 걸리는 상황이 발생합니다. 배치의 처리 속도가 중요하지 않다면 문제가 되지 않지만 다른 배치와 dependency가 있어 주어진 시간 내에 완료가 되어야 하는 상황도 빈번하게 발생합니다. 이에 대한 해결책으로 배치의 처리 속도를 향상하는 병렬 처리를 적용해 볼 수 있습니다. Spring Batch에서 데이터를 병렬 처리하는 방법은 다양하기 때문에 상황에 맞게 적절한 병렬 처리 기술을 선택하는 것은 중요합니다. 이번 포스팅에서는 단일 프로세스에서 성능 개선을 위한 chunk 병렬 처리 기술에 대한 특징을 알아보겠습니다. Chunk에 관한 Background 본격적으로 들어가기 앞서 spring batch에서는 데이터를 어떻게 처리하는지 알고 있어야 합니다. 대..
들어가며 배치 작업을 실행하다 보면 실패 상황에 빈번하게 직면하게 됩니다. 배치를 실패한 경우 단순하게 재시작을 해서 처리하는 방법도 있지만, 시간이 오래 걸리는 배치의 경우 처음부터 다시 실행하는 게 쉽지 않습니다. 다행히 Spring Batch에서는 ItemStream을 제공합니다. 이번에는 ItemStream을 활용하여 어떻게 재시작 관점에서의 문제를 해결할 수 있는지 정리해 봤습니다. BATCH_STEP_EXECUTION_CONTEXT 테이블 ItemStream을 살펴보기 전 BATCH_STEP_EXECUTION_CONTEXT 테이블을 설명드리겠습니다. 이 테이블은 Spring Batch에서 관리하는 메타데이터 테이블 중 하나입니다. Spring Batch 공식 문서에서는 이 테이블을 다음과 같이..
들어가며 최근 event기반 아키텍처에 관한 흥미로운 글을 읽었습니다. 요약하자면 이벤트 기반으로 느슨한 결합을 만드는 방식에 관한 내용을 담고 있는데 실제로 한번 구현을 해보면 재밌을 것 같다는 생각이 들었습니다. 그래서 유저 회원 가입 상황에 대해서 이벤트 기반으로 관심사를 분리하여 느슨한 결합을 만드는 구조를 한번 코드로 구현해 봤습니다. 회원 가입 요청이 들어오면 A서비스에서는 회원 가입이 완료되면 회원 가입 알림 메시지와 신규 유저 쿠폰이 발급됩니다. msa로 user, notification, coupon서비스가 각각 분리되어있다면 다음과 같이 처리할 수 있습니다. @Transactional fun createUser(createUserInput: CreateUserInput) { val ne..
Introduce GraphQL은 rest api와 달리 하나의 엔드포인트를 가지며 클라이언트는 정의된 스키마에 의해 원하는 필드를 자유롭게 조회할 수 있다. 예를들어, 아래와 같이 스키마가 정의되어 있다면 schema.graphqls type Query { product(id: ID!): Product! } type Product { id: ID! name: String! shop: Shop! } type Shop { id: ID! name: String! } 클라이언트는 다양한 방식의 쿼리가 가능하다. { product(i: "1"){ id name shop{ id name } } } ... { product(id: "1"){ name } } ... { product(id: "1"){ id shop{..
이번에는 엔티티 수정과정을 디버깅해보자. 엔티티를 수정하면 jpa에서는 dirty checking을 하고 update쿼리를 생성해준다. 정확히는 flush과정을 디버깅한다. 수정 과정 @Test @Transactional fun `update order`() { val order = Order(price = 1000) orderJpaRepository.save(order) order.price = 2000 orderJpaRepository.flush() } 먼저, order가 저장되는 부분에서 알고 넘어갈 부분이 있다. entitiy가 영속화되면 영속성 컨텍스트 내부에 entityEntryContext에 entityEntry가 저장된다. 이 entityEntry에는 loadState라는 것이 있다. 이 ..
이번에는 조회 과정을 디버깅해보자. 조회는 2가지 케이스로 나뉜다. 1. 영속성 컨텍스트에 존재하지 않아 db조회가 필요한 경우 2. 영속성 컨텍스트에 값이 존재해 1차 캐시를 반환하는 경우 (db 조회가 필요하지 않은 경우) 조회 과정 @Test @Transactional fun `find order`() { orderJpaRepository.findById(1L) } 먼저 find가 발생하면 DefaultLoadEventListener에 onLoad메서드가 호출된다. 이 메서드는 doOnLoad를 호출한다. 우선 doOnLoad는 session으로부터 EntityKey를 load 하는데, EntityKey는 entity의 id로 구성된 영속성 컨텍스트에서 엔티티를 구분해주는 key이다. 그리고 이어서..
이번 포스팅에서는 트랜잭션상에서 영속성 컨텍스트가 코드상으로 어떻게 사용되는지 확인해보려고 한다. 그전에 디버깅에 유용한 static 메서드를 소개한다. TransactionSynchronizationManager.getResourceMap() 이 메서드는 현재 스레드에 바인딩된 트랜잭션 자원을 확인해볼 수 있다. 예를 들어 아래 코드에서 이 메서드를 실행하면 트랜잭션 실행으로 entityMangerHolder와, datasource가 바인딩될 것을 알 수 있다. 저장 과정 persistanceContext는 entity를 저장하는 환경이다. entityManager를 사용해서 entity를 등록, 조회하는 경우 entityManger는 persistanceContext에 entity를 저장한다. 이제 ..
스프링은 JDK Dynamic Proxy, CGLIB의 프록시 생성 패턴을 사용한다. 이전 글에서 소개한 것 처럼 JDK Dynamic Proxy는 리플렉션을 사용하며 인터페이스가 반드시 필요했다. 반면, CGLIB는 바이트 코드를 조작해서 프록시를 만들고 상속을 사용하기 때문에 구체 클래스만으로도 프록시 생성이 가능했다. 하지만, 매번 코드상의 인터페이스 유무를 확인해서 JDK Dynamic Proxy의 InvocationHandler, CGLIB의 MethodInterceptor를 구현하기 쉽지 않다. 또한, 프록시 로직이 같을 때 인터페이스 유무가 다르다면 같은 내용의 InvocationHandler, MethodInterceptor를 작성해야 한다. 꽤 번거롭다. 스프링의 프록시 팩토리는 프록시 ..