<feed xmlns="http://www.w3.org/2005/Atom"> <id>https://jih00njung.github.io/</id><title>Jih0on의 블로그</title><subtitle></subtitle> <updated>2026-07-02T15:07:37+09:00</updated> <author> <name>Jih0on</name> <uri>https://jih00njung.github.io/</uri> </author><link rel="self" type="application/atom+xml" href="https://jih00njung.github.io/feed.xml"/><link rel="alternate" type="text/html" hreflang="ko-KR" href="https://jih00njung.github.io/"/> <generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator> <rights> © 2026 Jih0on </rights> <icon>/assets/img/favicons/favicon.ico</icon> <logo>/assets/img/favicons/favicon-96x96.png</logo> <entry><title>[order] JPA N+1 문제 개선: FETCH 조인과 IN</title><link href="https://jih00njung.github.io/posts/JPA-N+1-%EB%AC%B8%EC%A0%9C-%EA%B0%9C%EC%84%A0/" rel="alternate" type="text/html" title="[order] JPA N+1 문제 개선: FETCH 조인과 IN" /><published>2026-07-02T14:23:12+09:00</published> <updated>2026-07-02T15:07:16+09:00</updated> <id>https://jih00njung.github.io/posts/JPA-N+1-%EB%AC%B8%EC%A0%9C-%EA%B0%9C%EC%84%A0/</id> <content type="text/html" src="https://jih00njung.github.io/posts/JPA-N+1-%EB%AC%B8%EC%A0%9C-%EA%B0%9C%EC%84%A0/" /> <author> <name>Jih0on</name> </author> <category term="SpringBoot" /> <category term="order-system" /> <summary>N+1 문제가 발생했다. 주문 시스템을 개발하며 주문 내역 조회 API를 구현했다. 기능이 정상적으로 동작하는 것을 확인한 후, 실제 쿼리가 어떻게 발생하고 있는지 성능을 점검해 보기로 했다. 이를 위해 애플리케이션 속성에 다음 설정을 추가하여 쿼리 발생량을 확인했다. spring.jpa.show-sql: true / spring.jpa.properties.hibernate.format_sql: true: 실행되는 쿼리를 로그에서 확인 spring.jpa.properties.hibernate.generate_statistics=true: Hibernate가 실행한 총 쿼리 개수 및 통계 분석 띄우기 설정 후 주문 내역 조회 API를 테스트해 본 결과, 전형적인 N+1 문제가 발생하고 ...</summary> </entry> <entry><title>[order] 재고 차감에서 갱신 손실을 해결하며 이해한 트랜잭션 락</title><link href="https://jih00njung.github.io/posts/%EC%9E%AC%EA%B3%A0-%EC%B0%A8%EA%B0%90%EC%97%90%EC%84%9C-%EA%B0%B1%EC%8B%A0-%EC%86%90%EC%8B%A4%EC%9D%84-%ED%95%B4%EA%B2%B0%ED%95%98%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%9C-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EB%9D%BD/" rel="alternate" type="text/html" title="[order] 재고 차감에서 갱신 손실을 해결하며 이해한 트랜잭션 락" /><published>2026-06-25T17:53:18+09:00</published> <updated>2026-06-25T17:53:18+09:00</updated> <id>https://jih00njung.github.io/posts/%EC%9E%AC%EA%B3%A0-%EC%B0%A8%EA%B0%90%EC%97%90%EC%84%9C-%EA%B0%B1%EC%8B%A0-%EC%86%90%EC%8B%A4%EC%9D%84-%ED%95%B4%EA%B2%B0%ED%95%98%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%9C-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EB%9D%BD/</id> <content type="text/html" src="https://jih00njung.github.io/posts/%EC%9E%AC%EA%B3%A0-%EC%B0%A8%EA%B0%90%EC%97%90%EC%84%9C-%EA%B0%B1%EC%8B%A0-%EC%86%90%EC%8B%A4%EC%9D%84-%ED%95%B4%EA%B2%B0%ED%95%98%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%9C-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EB%9D%BD/" /> <author> <name>Jih0on</name> </author> <category term="SpringBoot" /> <category term="order-system" /> <summary>왜 동시성 문제에 관심을 가졌는가? 기존 프로젝트에서는 트랜잭션이 내부적으로 어떻게 동작하는지 깊이 이해하지 못한 채, 하나의 작업을 원자적으로 처리하기 위한 용도로만 @Transactional을 사용해 왔다. 그래서 여러 트랜잭션이 동시에 동일한 데이터를 수정할 때도 의도한 대로 데이터 무결성이 지켜지는지 확신할 수 없었다. 그래서 이번 주문 프로젝트에서는 재고 차감 로직에서 의도적으로 동시성 문제(갱신 손실)를 발생시켜 보고, 이를 다양한 락(Lock) 메커니즘을 통해 해결해 나가는 과정을 경험해 보기로 했다. 갱신 손실이 발생했다. 현재 재고가 10개인 상품에 대해 스레드 A와 B가 동시에 접근하여 1개씩 차감을 시도한다고 가정해 보자. 두 스레드는 모두 DB에서 재고 10개를 읽어온다. ...</summary> </entry> <entry><title>[order] 결제와 배송을 분리하며 이해한 트랜잭션 셀프 인보케이션</title><link href="https://jih00njung.github.io/posts/%EA%B2%B0%EC%A0%9C%EC%99%80-%EB%B0%B0%EC%86%A1%EC%9D%84-%EB%B6%84%EB%A6%AC%ED%95%98%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%9C-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EC%85%80%ED%94%84-%EC%9D%B8%EB%B3%B4%EC%BC%80%EC%9D%B4%EC%85%98/" rel="alternate" type="text/html" title="[order] 결제와 배송을 분리하며 이해한 트랜잭션 셀프 인보케이션" /><published>2026-06-18T18:20:17+09:00</published> <updated>2026-06-28T15:08:32+09:00</updated> <id>https://jih00njung.github.io/posts/%EA%B2%B0%EC%A0%9C%EC%99%80-%EB%B0%B0%EC%86%A1%EC%9D%84-%EB%B6%84%EB%A6%AC%ED%95%98%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%9C-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EC%85%80%ED%94%84-%EC%9D%B8%EB%B3%B4%EC%BC%80%EC%9D%B4%EC%85%98/</id> <content type="text/html" src="https://jih00njung.github.io/posts/%EA%B2%B0%EC%A0%9C%EC%99%80-%EB%B0%B0%EC%86%A1%EC%9D%84-%EB%B6%84%EB%A6%AC%ED%95%98%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%9C-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EC%85%80%ED%94%84-%EC%9D%B8%EB%B3%B4%EC%BC%80%EC%9D%B4%EC%85%98/" /> <author> <name>Jih0on</name> </author> <category term="SpringBoot" /> <category term="order-system" /> <summary>주문 시스템을 구현하면서 결제 완료 후 배송 정보를 생성하는 기능을 추가하고 있었다. 처음에는 같은 서비스 내부에서 배송 생성 메서드를 호출하는 단순한 구조를 생각했다. 기능적으로는 문제가 없었지만, 트랜잭션 학습 과정에서 객체가 자기 자신의 메서드를 직접 호출하는 셀프 인보케이션 개념을 알게 되었다. payment.complete(); createShipping(payment.getOrder()); 현재 구조에서는 별다른 문제가 없지만, 추후 배송 생성 로직에 별도의 트랜잭션 전파 옵션을 적용하거나 독립적인 처리 흐름이 필요해질 경우 예상과 다른 동작이 발생할 수 있다고 한다. 그래서 왜 이런 현상이 발생하는지 직접 원인을 분석해보았다. 트랜잭션 셀프 인보케이션이란? 스프링의 @Transac...</summary> </entry> <entry><title>[order] 엔티티는 왜 데이터만 들고 있으면 안 될까?</title><link href="https://jih00njung.github.io/posts/%EC%97%94%ED%8B%B0%ED%8B%B0%EB%8A%94-%EC%99%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A7%8C-%EB%93%A4%EA%B3%A0-%EC%9E%88%EC%9C%BC%EB%A9%B4-%EC%95%88-%EB%90%A0%EA%B9%8C/" rel="alternate" type="text/html" title="[order] 엔티티는 왜 데이터만 들고 있으면 안 될까?" /><published>2026-06-11T14:05:23+09:00</published> <updated>2026-06-28T15:08:32+09:00</updated> <id>https://jih00njung.github.io/posts/%EC%97%94%ED%8B%B0%ED%8B%B0%EB%8A%94-%EC%99%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A7%8C-%EB%93%A4%EA%B3%A0-%EC%9E%88%EC%9C%BC%EB%A9%B4-%EC%95%88-%EB%90%A0%EA%B9%8C/</id> <content type="text/html" src="https://jih00njung.github.io/posts/%EC%97%94%ED%8B%B0%ED%8B%B0%EB%8A%94-%EC%99%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A7%8C-%EB%93%A4%EA%B3%A0-%EC%9E%88%EC%9C%BC%EB%A9%B4-%EC%95%88-%EB%90%A0%EA%B9%8C/" /> <author> <name>Jih0on</name> </author> <category term="SpringBoot" /> <category term="order-system" /> <summary>나는 코드를 잘 짜고 있는 줄 알았다 과거 프로젝트를 진행할 때, 나의 1순위 목표는 가독성이었다. 그래서 서비스 로직을 메인 메서드와 여러 개의 private 서브 메서드로 쪼갰다. 그리고 메인 메서드에서 private 메서드를 호출하여 로직을 처리하도록 만들었다. 이렇게 했더니 자잘한 기능별로 분리되어 코드가 한눈에 들어왔고, 관련된 로직이 하나의 서비스 클래스 안에 모여있어 유지보수가 편해졌다고 자부했다. // 예시로 가져온 집현전 메인-서브 메서드 구조 // 메인 메서드 - 주소 분리 (시군구, 동, 번, 지, 동, 호) public Map&amp;lt;String, String&amp;gt; splitAddressDetails(String address) { String[] pa...</summary> </entry> <entry><title>[order] 주문 시스템 (2)</title><link href="https://jih00njung.github.io/posts/%EC%A3%BC%EB%AC%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C(2)/" rel="alternate" type="text/html" title="[order] 주문 시스템 (2)" /><published>2026-06-06T16:01:53+09:00</published> <updated>2026-06-28T15:08:32+09:00</updated> <id>https://jih00njung.github.io/posts/%EC%A3%BC%EB%AC%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C(2)/</id> <content type="text/html" src="https://jih00njung.github.io/posts/%EC%A3%BC%EB%AC%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C(2)/" /> <author> <name>Jih0on</name> </author> <category term="SpringBoot" /> <category term="order-system" /> <summary>5. ERD 설계 처음에는 주문과 결제를 식별관계로 설정하려고 하였다. 주문과 결제는 1:1 관계이며 결제는 주문이 존재해야만 생성될 수 있기 때문에 식별관계로 모델링하는 것이 자연스럽다고 생각하였다. 하지만 실무에서는 유지보수성과 확장성을 고려하여 비식별관계를 사용하는 경우가 많다. 그리고 식별관계로 설정하면 주문 ID가 결제 테이블에서 PK와 FK의 역할을 동시에 수행하게 되는데, 실무에서는 하나의 컬럼이 여러 역할을 가지는 구조를 지양하는 경향이 있다. 그래서 향후 부분 결제, 재결제, 환불 이력 관리 등 요구사항이 추가될 경우 결제가 주문과 독립적인 식별자를 가지는 것이 확장에 유리하다고 판단하여 비식별관계로 설계하였다. 6. 트랜잭션 설계 상품 등록, 상품 수정, 상품 삭제 상품 주...</summary> </entry> </feed>
