<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Performance on Gukin Han</title>
    <link>https://gukin.dev/tags/performance/</link>
    <description>Recent content in Performance on Gukin Han</description>
    <generator>Hugo</generator>
    <language>ko-kr</language>
    <lastBuildDate>Sun, 11 Jan 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://gukin.dev/tags/performance/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>자바 플랫폼 vs 가상 스레드 - 언제, 왜 성능 차이가 나는가?</title>
      <link>https://gukin.dev/posts/platform-vs-virtual-thread-benchmark/</link>
      <pubDate>Sun, 11 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://gukin.dev/posts/platform-vs-virtual-thread-benchmark/</guid>
      <description>&lt;h2 id=&#34;요약&#34;&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;가상 스레드는 CPU성능을 높이는 기술이 아닌, 대기 중인 스레드의 점유 비용을 낮추는 동시성 모델이다.&lt;/li&gt;
&lt;li&gt;스파이크 트래픽 환경에서 I/O-bound 작업은 가상 스레드로 인해 &lt;strong&gt;큐 대기와 p95 지연이 크게 줄어들었다.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;CPU-bound 작업에서는 스레드 모델 변경만으로 유의미한 성능 차이가 나타나지 않았다.&lt;/li&gt;
&lt;li&gt;가상 스레드는 병목을 제거하기보다, 병목의 위치를 스레드에서 다른 계층(DB, 외부 API 등)으로 이동시킨다.&lt;/li&gt;
&lt;li&gt;따라서 가상 스레드 도입은 성능 최적화 문제가 아니라, &lt;strong&gt;백프레셔/타임아웃/제한 등의 설계를 포함한 시스템 설계 문제&lt;/strong&gt;로 여겨야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;문제&#34;&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&#34;가상 스레드와 캐리어 스레드의 맵핑&#34; loading=&#34;lazy&#34; src=&#34;https://gukin.dev/posts/platform-vs-virtual-thread-benchmark/img.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>상관 서브쿼리로 인한 읽기 병목 개선</title>
      <link>https://gukin.dev/posts/correlated-subquery-read-bottleneck/</link>
      <pubDate>Sat, 13 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://gukin.dev/posts/correlated-subquery-read-bottleneck/</guid>
      <description>&lt;h2 id=&#34;요약&#34;&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;문제
&lt;ul&gt;
&lt;li&gt;운영 환경에서 조회 API 응답 지연(1초 이상) 이슈 발생&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;상관 서브쿼리로 인한 N+1 패턴&lt;/strong&gt;이 DB 레벨에서 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;과정
&lt;ul&gt;
&lt;li&gt;실행 계획 분석을 통해 Nested Loop 반복 실행과 &lt;strong&gt;옵티마이저 통계 오류&lt;/strong&gt;를 확인&lt;/li&gt;
&lt;li&gt;상관 서브쿼리를 &lt;strong&gt;CTE + Hash Join&lt;/strong&gt; 구조로 리팩토링&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;성과
&lt;ul&gt;
&lt;li&gt;서브쿼리 실행 &lt;strong&gt;92회에서 1회로 감소&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;총 실행 비용 &lt;strong&gt;246.0에서 40.6로 감소&lt;/strong&gt; (약 83% 개선, 6배 성능 향상)&lt;/li&gt;
&lt;li&gt;운영 데이터 기준으로 실행 계획 변화와 성능 개선을 수치로 검증&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;문제-배경&#34;&gt;문제 배경&lt;/h2&gt;
&lt;p&gt;운영 중인 서비스에서 특정 테넌트 기준 조회 API의 응답지연이 보고되었다. 슬로우 쿼리 분석 결과, 직원을 그룹화하는 테이블의 조회 쿼리 내부에 상관 서브쿼리(Correleated Subquery)가 포함되어있었다. 그 영향으로 메인 쿼리 결과 행 수만큼 서브쿼리가 반복 실행되는 문제가 발생했다.&lt;/p&gt;</description>
    </item>
    <item>
      <title>트랜잭션에서 이벤트로 - Sync / Async / Redis 성능 비교와 TTV 분석</title>
      <link>https://gukin.dev/posts/sync-async-redis-like-performance/</link>
      <pubDate>Fri, 29 Aug 2025 00:00:00 +0000</pubDate>
      <guid>https://gukin.dev/posts/sync-async-redis-like-performance/</guid>
      <description>&lt;h2 id=&#34;문제&#34;&gt;문제&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Transactional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;like&lt;/span&gt;(String loginId, Long productId) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 유저 조회&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    User user &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; userService.&lt;span style=&#34;color:#a6e22e&#34;&gt;getByLoginId&lt;/span&gt;(loginId);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 상품-좋아요 Insert&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;boolean&lt;/span&gt; isInserted &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; productLikeRepository
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .&lt;span style=&#34;color:#a6e22e&#34;&gt;insertIgnoreDuplicateKey&lt;/span&gt;(user.&lt;span style=&#34;color:#a6e22e&#34;&gt;getUserId&lt;/span&gt;(), productId);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;isInserted) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 3. 좋아요 수 집계 Update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    productRepository.&lt;span style=&#34;color:#a6e22e&#34;&gt;incrementLikeCount&lt;/span&gt;(productId);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;좋아요 기능에서 처음엔 모든 로직을 하나의 트랜잭션 안에서 &lt;strong&gt;동기적&lt;/strong&gt;(Sync)으로 처리&lt;/li&gt;
&lt;li&gt;안정적이지만 &lt;strong&gt;트랜잭션 크기&lt;/strong&gt;가 커지고, 상품 핫키에 경합으로 인한 &lt;strong&gt;병목&lt;/strong&gt;이 발생&lt;/li&gt;
&lt;li&gt;그래서, 이벤트 기반 설계를 통해 결합도를 낮추고(loosely coupled), 책임을 분리하려는 시도&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Github PR : &lt;a href=&#34;https://github.com/gukin-han/commercial-service/pull/7&#34;&gt;https://github.com/gukin-han/commercial-service/pull/7&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>정규화부터 캐싱까지 - 상품 목록 페이지네이션 최적화 과정</title>
      <link>https://gukin.dev/posts/read-heavy-pagination-optimization/</link>
      <pubDate>Fri, 15 Aug 2025 00:00:00 +0000</pubDate>
      <guid>https://gukin.dev/posts/read-heavy-pagination-optimization/</guid>
      <description>&lt;h2 id=&#34;요약&#34;&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;정규화 쿼리(집계 + 정렬)&lt;/strong&gt; → 풀스캔 + filesort로 &lt;strong&gt;~17초&lt;/strong&gt; 소요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;역정규화 + 정렬 포함 인덱스&lt;/strong&gt; → &lt;strong&gt;~227ms&lt;/strong&gt; (약 76배 향상).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OFFSET 페이지네이션&lt;/strong&gt; → 인덱스 순차 스캔 시작 → 임계점에서 Table Scan + Filesort로 전환 → 이후 응답시간 급등.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;전환 전 일정한 속도&lt;/strong&gt;는 InnoDB 버퍼 풀/캐시 히트율 덕분.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keyset(Seek) 페이지네이션&lt;/strong&gt; → 깊은 페이지에서도 일정 성능 (421ms → 31ms, 92.6% 단축).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;인덱스 설계&lt;/strong&gt;는 핫 트래픽 패턴(브랜드 + 인기순/최신순/최저가순)에 맞춘 3개의 복합 인덱스 유지가 가성비 최적.
&lt;ul&gt;
&lt;li&gt;설계 원칙: 필터 선두 → 정렬키 → tie-breaker(id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;캐시(Cache-Aside)&lt;/strong&gt; 적용 시 200RPS에서도 DB I/O 부하 없이 ms 단위 응답 가능.
&lt;ul&gt;
&lt;li&gt;단, TTL·Evict 정책·실시간성 요구사항·정합성 유지·스탬피드 방지 등 고려 필수.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;결론: &lt;strong&gt;정규화/역정규화 → 인덱스 설계 → 페이지네이션 전략 → 캐싱&lt;/strong&gt;이 단계적으로 맞물려 성능을 좌우함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;문제-정의와-가설&#34;&gt;문제 정의와 가설&lt;/h2&gt;
&lt;p&gt;웹 서비스에서는 쓰기 보다 &lt;strong&gt;읽기 트래픽이 압도적으로 많다&lt;/strong&gt;는 글을 읽거나 실제로 경험해봤을 것이다.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
