⛅️ Recent ⛅️
-
인프라
Saga 패턴
해당 글은 '마이크로 서비스 패턴' 이라는 책에서 다룬 사가 패턴에 대해 정리하였습니다. 분산 트랜잭션? 마이크로서비스 아키텍처에서 단일 서비스 내부의 트랜잭션은 ACID를 보장하지만, 여러 시스템에 얽힌 트랜잭션은 구현하기가 까다롭기 때문에, 여러 서비스에 걸쳐 트랜잭션을 관리할 수 있는 매커니즘이 필요하다. 예시로 '주문 생성'을 본다면(createOrder()), 소비자 서비스, 주문 서비스, 주방 서비스, 회계 서비스 등 여러 서비스에 있는 데이터에 접근해야 하는데, 여기서 여러 DB에 걸친 데이터의 일관성을 유지할 수 있는 수단이 필요하다는 것이다. 이러한 수단 중 하나가 바로 분산 트랜잭션이다. 널리 알려져 있는 분산 트랜잭션 관리의 사실상 표준으로는 X/Open DTP(Distributed ..
-
카테고리 없음
Mocks Aren't Stubs 번역
원문 Mock과 Stub의 차이를 살펴보다가 과거 마틴 파울러의 글을 발견하게 되었다. 이런 논쟁, 차이점도 있었구나를 보는 정도로 이 글을 읽으면서 번역한 내용을 기록한다 https://martinfowler.com/articles/mocksArentStubs.html Mocks Aren't Stubs Explaining the difference between Mock Objects and Stubs (together with other forms of Test Double). Also the difference between classical and mockist styles of unit testing. martinfowler.com 참고로 마틴파울러는 번역에 대한 별다른 제재를 두지 않았다. h..
-
인프라
Grafana Loki와 LogQL 에 대해 알아보기
최근에 Grafana Loki 사용법을 익히고, 대시보드 구성을 연구하는데 많은 시간을 들이게 되었다. 이와 관련해 Loki의 개념과 자꾸 헷갈리는 LogQL 문법을 공식 문서 기반으로 정리해보려 한다. Loki란? Loki is a horizontally-scalable, highly-available, multi-tenant log aggregation system inspired by Prometheus. It is designed to be very cost effective and easy to operate. It does not index the contents of the logs, but rather a set of labels for each log stream. 로키는 Promethe..
-
JPA
[Spring Batch] JpaPagingItemReader + JpaItemWriter를 사용했 때겪었던 문제점 (2)
(수정중) 다시한번 언급하지만, 이 글의 전제는 '애초에 이렇게 배치를 구현하면 안된다'로, JpaPagingItemReader, JpaItemWriter를 가지고 이것 저것 실험하면서 경험한 내용을 정리한 글이다. 앞 글에서 아직 다 다루지 못한 문제가 남아있다. 바로 "마지막 청크는 5개 쿠폰에 대한 history는 정상적으로 한개씩만 쌓이고 있다" 라는 것이다. (어느정도 감이 왔을 수도 있지만...) 이에 대한 원인은 다른 예제로 설명해보려 한다. JpaItemWriter에서 Dirty Checking으로 엔티티 변경사항을 DB에 반영할 때 문제점 앞 글에서 발생한 자식엔티티 중복 저장에 대한 문제는 결국 reader와 writer에서 서로 다른 entityManager를 사용하고 있었기 때문이었..
-
스프링 부트
[Spring Batch] JpaPagingItemReader + JpaItemWriter를 사용했 때겪었던 문제점 (1)
최근 배치를 짜고 운영하다가 참으로 이상한 현상을 겪었는데, 이를 JpaPagingItemReader, JpaItemWriter의 내부 동작과 함께 원인을 정리해보려 한다. (aka. 나의 삽질 기록) 내 삽질 기록을 정리한 글을 통해 말하고자 하는 내용을 미리 정의하고 넘어가자면, 배치 reader로 조회한 엔티티를 그대로 사용하지말고 특정 필요한 값만 dto로 뽑아쓰는 방식을 취하자이다 (엔티티의 수정 x). 이 글은 내가 배치 reader로 조회한 엔티티 그대로를 직접 수정, dirty checking을 이용하다 생긴 문제로, 애초에 이렇게 구현하면 안된다가 전제로 깔린다. 그냥 배치에서 엔티티를 지직 볶고 하다가 깨닫게 된 몇가지 내용들을 정리한 글로 봐주길. 문제상황 예시 먼저 Coupon(쿠폰..
-
기록
글또 7기를 시작하며
글또 7기에 참여하게 되었슴다 작년 우테코 교육을 받던 때, 몇명 크루들 덕분에 글또라는 모임을 알게 되었다. 글쓰는 개발자 모임이라니, 6기 모집 한참 후에나 글또를 알게되어서 다음 모집이 열리면 기필코 신청하리라 마음 먹었었다. 당시에는 (그때 쓴 글의 퀄리티는 보장 못하지만 🙃)... 내가 배우고 경험하며 성장한 부분들을 남겨야하겠다는 약간의 강박과, 경험한 내용을 기록하고 공유하는 것에 대한 즐거움이 있었기에 꾸준히 기술 글을 작성하고 있었다. 이렇게 작성한 글들은 다른 크루들과 서로 작성한 글들을 공유하면서 좋은 영향력을 많이 받았었는데, 조금 더 넓은 분야에서 다양한 개발자들의 글을 더 많이 접하고 피드백을 받으며 조금이라도 더 질 높은 글을 쓰고 싶다는 욕심이 생겼었다. 그러다 올해는 취업을..
-
스프링 부트
@Transactional 메서드에서 다른 클래스의 @Async 메서드를 호출하면? (feat. 트랜잭션과 스레드)
서로 다른 스레드 간 트랜잭션 공유를 초점으로, 스프링이 트랜잭션을 어떻게 관리하는지 아주 일부분 관찰해본 글입니다. (참고) 아주*1000 간단한 테스트 환경 // main에 @EnableAsync @Transactional @Service class TxService( private val testEntityRepository: TestEntityRepository, private val innerService: AsyncService ) { fun saveOneAndCallException() { logger.info("[TxService][saveOneAndCallException] 호출. Thread id: ${Thread.currentThread().id}") // 테스트 엔티티 1 save ..
-
코틀린
[이펙티브 코틀린] 추상화 설계
이펙티브 코틀린을 읽다가 객체지향을 다룬 부분에서 남기고 싶은 내용들이 있어 조금 발췌하여 가볍게 정리해보았다. 추상화란 컴퓨터 과학에서 추상화는 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것이다. 대표적인 예로는 인터페이스가 있다. 클래스라는 복잡한 것에서 메서드와 프로퍼티만 추출해 간단하게 만들었기 때문이다. 프로그래밍에서의 추상화 추상화를 설계한다는 것은 단순히 모듈 또는 라이브러리로 분리한다는 의미가 아니다. 함수를 정의할 때, 그 구현을 함수의 시그니처 뒤에 숨기게 되는데 이가 바로 추상화이다. 만약 코틀린의 maxOf() 함수를 사용하지 않고 다음과 같이 사용한다고 해보자. val biggest = if (z > y) x else y 위 코드는 추상적인 것을..