안녕세계
ArchUnit이란?보통 팀마다 정해져있는 아키텍처가 문서로 작성되어 있거나 기존 코드의 아키텍처를 참조해가며, 개발을 진행하는 경우가 많을 것 입니다. 아키텍처에 위배되는 개발이 되는 것을 미연에 방지하기 위해서는 어떤 방법이 좋을까요? 팀에서 정의한 아키텍처를 위배했을때 코드리뷰를 통해서 잘못된 아키텍처를 바로 잡을 수도 있겠지만, 코드리뷰에서는 비즈니스 로직에 대한 검증을 중점적으로 하고 아키텍처와 관련된 부분은 자동화하는 편이 더 효율적일 것입니다. ArchUnit은 Java 애플리케이션의 아키텍처 규칙을 코드로 정의하고 테스트할 수 있게 해주는 오픈 소스 라이브러리입니다. 애플리케이션의 아키텍처가 복잡해지고 방대해질수록 각 계층 간의 의존성을 유지하고 코드의 일관성을 보장하는 것이 중요해집니다...
글또를 시작하며지난 글또 8기를 시작으로, 글또 9기 그리고 마지막 10기까지 참여하게 되었습니다. 글또라는 커뮤니티를 통해서 글쓰는 습관을 만들 수 있었고, 이 계기로 우아한형제들 기수블로그에 WMS 재고 이관을 위한 분산 락 사용기를 기고할 수 있었다고 생각합니다. 그래서 이제는 아는 것을 글로 정리하고 공유하는 것이 조금은 익숙해진 것 같습니다. 글또를 시작한지 2023년 2월 이니, 꾸준히 글을 쓴지 곧 2년이 되어지만 익숙해진 것 뿐 글쓰기라는 것은 여전히 참 어려운 것 같습니다.글또를 돌아보며10기에서는 지난 8기/9기 활동에서 얻은 것 외에도 다양한 소모임 활동과 새로운 분들을 만나 뵙도록 노력하고자 합니다. 8기에서는 글쓰기 급급했던 것 같고, 9기는 운영진 활동과 회사 업무를 병행하다보니..
@PostPersist와 @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)는 모두 Spring에서 트랜잭션 관련 이벤트를 처리하는데 사용됩니다. 두 어노테이션은 동작 시점과 사용 용도가 다르므로 차이를 이해하고 사용해야합니다. 본 포스팅에서는 두 어노테이션의 차이점에 대해 알아봅니다. @PostPersist동작 시점엔티티가 영속성 컨텍스트에 저장된 직후 호출됩니다. 즉, persist 메서드가 호출된 후를 의미합니다.데이터베이스에 INSERT 연산이 수행된 후 호출되며, 트랜잭션 commit이 되기 전에 호출됩니다.fun main() { val emf: EntityManagerFactory = Persistence.createEn..
2023년 12월 10일부터 2024년 5월 12일까지 약 6개월 간의 글또 9기 활동을 마무리하며 KTP 회고 글을 작성해 봅니다.Keep글또 9기를 마무리하며 앞으로도 유지하고 싶은 것은?글또 8기에 이어서 9기 활동을하면서 벌써 1년이 넘는 시간 동안 매달 1회 이상의 글을 작성했습니다. 지난 기수부터 활동한 덕분에 꾸준히 글 쓰는 습관을 유지할 수 있었고, 이제는 글을 쓰지 않으면 조금은 어색한 시점이 다가 온 것 같습니다. 앞으로도 글을 쓰는 활동을 이어가려고 합니다. 다만, IT 관련된 글이 아닌 다양한 주제의 글을 작성하고자 합니다. 이번 기수에서 발행한 글들이 모두 기술과 관련된 글이었다는 점은 조금 아쉬웠던 것 같습니다. IT 관련된 글이 아니더라도, 글을 쓴다는 행위 자체가 제 스스로에..
MDC란? MDC(Mapped Diagnostic Context)는 스레드 단위로 데이터를 읽고 쓸 수 있는 기능입니다. MDC를 사용하면 멀티 스레드 환경에서 각 스레드의 실행 컨텍스트를 구분할 수 있어서 모니터링시 추적에 용이합니다. 예를 들어 멀티 스레드 환경에서는 요청 순서대로 로그가 찍히지 않고, 로그가 섞여서 쌓이게 되므로 동일한 스레드의 컨텍스트를 추적하기 위해 MDC를 사용합니다. 스레드 로컬에 대해 알고 계시는 분들은 MDC와 스레드 로컬의 차이점이 무엇인지 궁금하실 수 있을 것 같습니다. 사실, MDC는 내부적으로 스레드 로컬을 사용하고 있어서 별도로 스레드 로컬을 선언할 필요없이 MDC를 바로 사용하면 됩니다. // MDC 내부 public class MDC { static final..
이번 포스팅에서는 제네릭과 무공변에 대해 알아보고, 무공변을 공변과 반공변으로 만드는 방법에 대해 알아봅니다. 우선, 제네릭에 대해 설명하기 위해 아이스크림 가게 예제를 만들어 보겠습니다. 현재 아이스크림 가게에는 초코 아이스크림과 민트 아이스크림이 있다고 가정해봅니다. interface IceCream class ChocoIceCream : IceCream class MintIceCream : IceCream 그리고 콘에 아이스크림을 올리는 put 메서드를 추가하고, 콘에서 아이스크림을 꺼내는 get 메서드를 추가합니다. class Cone { private val iceCreams: MutableList = mutableListOf() fun get(index: Int): IceCream { retu..
SSE(Server-Sent-Events)란? 웹 페이지가 새로운 데이터를 받기 위해서는 일반적으로 서버에 요청을 보내야 합니다. 그러나 SSE(Server-Sent Events)를 사용하면 서버가 요청 없이도 웹 페이지에 새로운 데이터를 전송할 수 있습니다. 이는 서버에서 클라이언트로 데이터를 주기적으로 전송해야 할 경우에 특히 유용합니다. 예를 들어, 서버가 특정 데이터의 변경 사항을 주기적으로 클라이언트에 알려주어야 하고, 클라이언트는 이를 대시보드 등의 화면에서 실시간으로 표시해야 하는 상황에서 활용될 수 있습니다. 웹소켓을 통한 구현도 가능하지만, 양방향 통신이 필요 없고 오직 서버에서 클라이언트로의 단방향 통신만 필요한 경우 SSE의 사용이 권장됩니다. SSE는 HTML5부터 지원되는 표준 스..
이전 포스팅에서 Redisson을 사용하여 Redis 분산 락을 손 쉽게 구현할 수 있는 방법에 대해서 알아보았습니다. 이번 포스팅에서는 분산 분산 락을 거는 위치에 따라 발생할 수 있는 문제에 대해 알아보고 권장하는 분산 락 위치에 대해 알아봅니다. 트랜잭션 이후 분산 락 분산 락을 건다는 의미는 결국 동일 자원에 대해 동시 작업하는 것을 제어하기 위함입니다. 그렇다면 우리는 분산 락을 건 상태에서 데이터베이스 트랜잭션과 관련된 작업을 시작해야합니다. 그런데 만약 데이터베이스 트랜잭션을 먼저 시작하고 분산 락을 걸게되면 어떻게 될까요? 종종 데이터베이스 트랜잭션이 먼저 시작된 이후 분산 락을 걸어도 별 다른 문제가 발생하지 않는고 생각할 수도 있습니다. 다음 그림을 살펴보겠습니다. 위 그림에서 처럼 트..