<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>bruni.log</title>
    <link>https://bruni-blog.pages.dev/</link>
    <atom:link href="https://bruni-blog.pages.dev/feed.xml" rel="self" type="application/rss+xml"/>
    <description>카멜레온 브루니가 DB·백엔드에서 실제로 터지는 문제를 한 편씩 적어요.</description>
    <language>ko</language>
    <item>
      <title>「구글 부업」 90분 영상 검증 — 애드센스의 맞는 말과 확인 안 되는 숫자</title>
      <link>https://bruni-blog.pages.dev/blog-adsense-side-job/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=blog-adsense-side-job</guid>
      <pubDate>Mon, 19 Oct 2026 00:00:00 GMT</pubDate>
      <category>운영 노트</category>
      <description>「구글 부업」 90분 영상을 끝까지 보고 정리했어요. 애드센스 수익 배분 68%와 지급일처럼 공식 문서와 맞는 주장, 확인할 수 없는 숫자, 따라 하면 계정이 막힐 수 있는 방법(AI 글 대량 발행·블로그 매매·명의 대여)을 표로 나눠 보여 드려요.</description>
    </item>
    <item>
      <title>AI 는 파이썬으로 짜는데 인프라는 왜 Rust 로 가나</title>
      <link>https://bruni-blog.pages.dev/ai-infra-rust/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=ai-infra-rust</guid>
      <pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate>
      <category>장애·확장</category>
      <description>AI 모델은 파이썬으로 짜는데 토크나이저·safetensors·Polars·추론 서버 속은 왜 Rust 로 바뀔까요. GPU 앞단의 CPU 일과 GIL, 메모리 안전, PyO3·maturin 패키지 코드까지 보여 주고, 언제 Rust 를 꺼낼지 순서를 정리했어요.</description>
    </item>
    <item>
      <title>느린 쿼리보다 총 시간 — pg_stat_statements 로 튜닝 순서 정하기</title>
      <link>https://bruni-blog.pages.dev/db-43/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-43</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>느린 쿼리 로그 1등을 고쳐도 지표가 안 움직이는 건 자주 도는 짧은 쿼리가 로그에 안 잡히기 때문이에요. pg_stat_statements 를 total_exec_time 으로 정렬해 우선순위를 정하고, 호출 수·최댓값·사용자 경로까지 함께 보는 법을 담았어요.</description>
    </item>
    <item>
      <title>조인 쿼리가 갑자기 느려졌을 때 — 추정이 어긋난 첫 노드 찾기</title>
      <link>https://bruni-blog.pages.dev/db-42/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-42</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>쿼리도 인덱스도 그대로인데 조인 순서가 뒤집혀 느려졌다면 원인은 대개 행 수 추정이에요. EXPLAIN ANALYZE 에서 rows 추정과 actual 이 처음 벌어진 노드를 찾고, ANALYZE·CREATE STATISTICS·서브쿼리로 바로잡는 순서를 정리했어요.</description>
    </item>
    <item>
      <title>Index Scan 인데 느린 이유 — EXPLAIN BUFFERS 로 원인 가르기</title>
      <link>https://bruni-blog.pages.dev/db-41/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-41</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>EXPLAIN 에 Index Scan 이 찍혔는데도 쿼리가 느릴 때 볼 숫자를 정리했어요. shared read·Rows Removed by Filter·loops·Heap Fetches 중 큰 값으로 원인을 가르고 커버링 인덱스·random_page_cost 로 고쳐요.</description>
    </item>
    <item>
      <title>인덱스 팽창(bloat) 확인하고 REINDEX CONCURRENTLY 로 줄이기</title>
      <link>https://bruni-blog.pages.dev/db-40/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-40</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>테이블은 그대로인데 인덱스만 커지는 인덱스 팽창이 무작위 UUID 키·잦은 갱신·대량 삭제에서 빨라지는 이유를 설명해요. 테이블 대비 인덱스 크기 비율로 확인하고, PostgreSQL 12 부터 되는 REINDEX CONCURRENTLY 로 줄이는 법과 예방책을 담았어요.</description>
    </item>
    <item>
      <title>COUNT(*) 는 결국 다 세는 일이다</title>
      <link>https://bruni-blog.pages.dev/db-39/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-39</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>목록 조회는 빠른데 전체 개수를 세는 COUNT(*) 만 몇 초씩 걸리는 이유를 MVCC 로 설명해요. pg_class 의 reltuples 로 근삿값 읽기, LIMIT 101 로 세다가 멈추기, 집계 테이블, 무한 스크롤로 총 개수 없애기 중 무엇을 고를지 정리했어요.</description>
    </item>
    <item>
      <title>NOT IN 에 NULL 이 섞이면 결과가 0건 — NULL 과 인덱스</title>
      <link>https://bruni-blog.pages.dev/db-38/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-38</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>NOT IN 서브쿼리에 NULL 이 하나라도 있으면 결과가 통째로 비는 이유를 NULL 비교 규칙으로 풀어요. NOT EXISTS 로 바꾸는 법, IS NULL 조회용 부분 인덱스, DB 마다 다른 NULL 정렬 위치와 유니크 제약의 함정도 함께 다뤄요.</description>
    </item>
    <item>
      <title>OR 조건이 인덱스를 못 타는 이유 — UNION·IN 으로 나누기</title>
      <link>https://bruni-blog.pages.dev/db-37/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-37</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>다른 컬럼을 OR 로 묶으면 인덱스 하나로 풀 수 없어 순차 스캔으로 빠지기 쉬워요. 같은 컬럼이면 IN 으로, 다른 컬럼이면 UNION ALL 로 나누는 법과 EXPLAIN 에서 BitmapOr·Seq Scan 을 가려 보는 법까지 정리했어요.</description>
    </item>
    <item>
      <title>여섯 번째 실행부터 느려지는 쿼리 — PostgreSQL generic plan 문제</title>
      <link>https://bruni-blog.pages.dev/db-36/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-36</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>같은 커넥션에서 다섯 번은 빠르다가 여섯 번째부터 느려지면 PostgreSQL 이 맞춤 계획에서 일반 계획(generic plan)으로 바꾼 거예요. 치우친 데이터에서 느려지는 이유, 재시작하면 낫는 이유, plan_cache_mode 로 맞춤 계획을 강제하는 법을 정리했어요.</description>
    </item>
    <item>
      <title>정렬이 디스크로 넘어갈 때 — work_mem 과 external merge</title>
      <link>https://bruni-blog.pages.dev/db-35/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-35</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>EXPLAIN 에 Sort Method: external merge 가 뜨면 정렬이 work_mem 을 넘어 디스크로 간 거예요. work_mem 이 정렬 작업 하나당 값이라 트래픽이 높을 때만 느려지는 이유와 인덱스로 정렬 없애기, 세션 단위로 올리기를 정리했어요.</description>
    </item>
    <item>
      <title>인덱스 온리 스캔이 안 되는 이유</title>
      <link>https://bruni-blog.pages.dev/db-34/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-34</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>필요한 컬럼을 다 넣었는데 PostgreSQL 이 테이블을 다시 읽는 건 가시성 맵 때문이에요. VACUUM 이 표시를 붙이기 전에는 Index Only Scan 이어도 Heap Fetches 가 생겨요. 포함 컬럼(INCLUDE)과 쓰기 많은 테이블의 한계를 정리했어요.</description>
    </item>
    <item>
      <title>LIMIT 이 붙으면 계획이 통째로 바뀐다</title>
      <link>https://bruni-blog.pages.dev/db-33/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-33</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>LIMIT 을 붙였더니 오히려 느려지거나 LIMIT 10 과 100 의 속도가 크게 뒤집히는 이유를 다뤄요. 옵티마이저가 첫 몇 행을 빨리 내는 계획을 고르는 방식과 ORDER BY + LIMIT 에 맞는 복합 인덱스, 정렬 키 동점과 OFFSET 문제를 정리했어요.</description>
    </item>
    <item>
      <title>EXPLAIN ANALYZE 읽는 법 — 추정 행 수와 실제 행 수 비교하기</title>
      <link>https://bruni-blog.pages.dev/db-32/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-32</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>EXPLAIN 의 비용은 밀리초가 아니고, 진단은 EXPLAIN ANALYZE 의 추정 행 수와 실제 행 수 차이에서 시작해요. loops 곱하기, 부모에서 자식 시간 빼기, BUFFERS 로 읽은 블록 보기, 필터로 버린 행, 실제 파라미터로 실행하기를 정리했어요.</description>
    </item>
    <item>
      <title>@Transactional(readOnly = true) 를 안 붙이면 복제본으로 안 간다</title>
      <link>https://bruni-blog.pages.dev/db-31/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-31</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>조회만 하는데 쓰기 트랜잭션으로 열리면 라우터가 주 서버로 보내 읽기 복제본이 놀아요. @Transactional(readOnly = true) 선언이 DB·프레임워크·라우팅에서 바꾸는 것과 힌트와 강제의 차이, 복제 지연을 다루는 규칙을 정리했어요.</description>
    </item>
    <item>
      <title>배치를 트랜잭션 하나로 돌리지 마라</title>
      <link>https://bruni-blog.pages.dev/db-30/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-30</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>백만 건 배치를 트랜잭션 하나로 감싸면 두 시간 동안 커넥션·스냅샷·락이 잡혀 서비스가 느려지고, 실패하면 처음부터 다시 해야 해요. 1초 단위 청크, 처리와 같은 트랜잭션에 남기는 체크포인트, 대상 범위 인자, 멱등 처리, 복제 지연 조절을 정리했어요.</description>
    </item>
    <item>
      <title>낙관적 락 vs 비관적 락 — 충돌 확률로 고르는 기준</title>
      <link>https://bruni-blog.pages.dev/db-29/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-29</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>낙관적 잠금과 비관적 잠금은 성능 우열이 아니라 충돌률에 따라 유불리가 뒤집혀요. 먼저 원자적 갱신으로 풀리는지 보고 충돌률·대기 허용·재시도 부수 효과 순으로 판단하는 기준, NOWAIT, 재시도 상한, 큐로 직렬화하는 경우를 정리했어요.</description>
    </item>
    <item>
      <title>트랜잭션은 짧게 — 경계가 곧 비용이다</title>
      <link>https://bruni-blog.pages.dev/db-28/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-28</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>요청 전체를 트랜잭션으로 감싸면 커넥션·스냅샷·락이 그 시간 내내 잡혀 커넥션 부족, 테이블 팽창, 락 경합이 한꺼번에 나요. 경계를 서비스 계층에 두기, 외부 호출과 계산 빼기, 락 잡는 쓰기를 마지막에 두기, 트랜잭션 길이 지표를 정리했어요.</description>
    </item>
    <item>
      <title>아웃박스 패턴 — 커밋되기 전에 이벤트를 보내지 마라</title>
      <link>https://bruni-blog.pages.dev/db-27/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-27</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>저장 직후 이벤트를 발행하면 커밋 전에 이벤트가 나가거나 롤백된 주문의 알림이 가고, 순서를 바꾸면 이벤트가 유실돼요. 같은 트랜잭션에 아웃박스 테이블로 기록하고 워커가 발행하는 구조, 적어도 한 번 전달과 멱등 소비자, 폴링과 CDC 를 정리했어요.</description>
    </item>
    <item>
      <title>SKIP LOCKED 로 만드는 작업 큐</title>
      <link>https://bruni-blog.pages.dev/db-26/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-26</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>DB 테이블로 만든 작업 큐에서 워커를 늘려도 FOR UPDATE 때문에 한 행 앞에 줄을 서는 문제를 SKIP LOCKED 로 풀어요. 워커가 죽으면 락이 풀려 다시 집히는 이유, 대기 작업만 담는 부분 인덱스, 재시도 컬럼, 완료 작업 정리, 브로커와의 비교를 정리했어요.</description>
    </item>
    <item>
      <title>REQUIRES_NEW 가 커넥션 풀을 말린다 — 요청 하나가 커넥션 둘을 쥘 때</title>
      <link>https://bruni-blog.pages.dev/db-25/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-25</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>@Transactional 안에서 REQUIRES_NEW 로 새 트랜잭션을 열면 바깥 커넥션을 쥔 채 하나를 더 요청해요. 동시 요청이 풀 크기를 넘는 순간 앱이 스스로 교착에 빠지는 이유와 트랜잭션 밖으로 빼기, 아웃박스, 저장점, 풀 대기 지표를 정리했어요.</description>
    </item>
    <item>
      <title>@Transactional 롤백이 안 될 때 — 자기 호출과 프록시</title>
      <link>https://bruni-blog.pages.dev/db-24/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-24</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>@Transactional 을 붙였는데 롤백이 안 되면 대개 프록시를 거치지 않은 호출이에요. 같은 클래스 안의 자기 호출, private·final 메서드, new 로 만든 객체, 삼킨 예외, rollbackFor 규칙, 비동기 경계와 트랜잭션 로그 확인법을 정리했어요.</description>
    </item>
    <item>
      <title>쓰기 스큐 — 각자는 옳은데 합치면 틀리다</title>
      <link>https://bruni-blog.pages.dev/db-23/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-23</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>두 트랜잭션이 서로 다른 행을 쓰지만 같은 집합을 읽고 판단하면 당직자가 0명이 되는 쓰기 스큐가 생겨요. REPEATABLE READ 로 못 막는 이유와 조건을 UPDATE 에 합치기, 배제 제약, 충돌 지점 행, 그 트랜잭션만 SERIALIZABLE 로 올리기를 정리했어요.</description>
    </item>
    <item>
      <title>갱신 손실(lost update) — 동시에 들어온 포인트 적립이 한 번만 반영될 때</title>
      <link>https://bruni-blog.pages.dev/db-22/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-22</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>잔액을 읽고 더해서 저장하는 코드는 동시 요청에서 한쪽 쓰기를 덮어써 갱신 손실이 나요. 기본 격리 수준이 이걸 못 막는 이유와 balance = balance + 10 같은 원자적 갱신, 버전 컬럼 낙관적 잠금, 비관적 잠금을 고르는 기준을 정리했어요.</description>
    </item>
    <item>
      <title>트랜잭션 안에서 외부 API 를 부르지 마라</title>
      <link>https://bruni-blog.pages.dev/db-20/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-20</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>트랜잭션 안에서 결제 API 를 부르면 응답을 기다리는 동안 커넥션이 idle in transaction 으로 묶여, 결제사가 조금만 느려져도 커넥션 풀이 고갈되고 서비스 전체가 멈춰요. 커밋 뒤로 호출 빼기, 아웃박스 패턴, 멱등키, 타임아웃을 정리했어요.</description>
    </item>
    <item>
      <title>JSON 컬럼은 스키마를 미루는 빚이다</title>
      <link>https://bruni-blog.pages.dev/db-19/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-19</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>JSON 컬럼은 스키마를 없앤 게 아니라 애플리케이션으로 옮긴 거라, 시간이 지나면 키를 아무도 모르고 JSON 안 값 조회는 통계 없이 느려져요. WHERE·정렬·집계에 쓰는 키를 컬럼으로 승격하는 순서와 json·jsonb 차이, GIN·표현식 인덱스를 정리했어요.</description>
    </item>
    <item>
      <title>대량 적재 뒤 쿼리가 느려지면 — ANALYZE 와 낡은 통계</title>
      <link>https://bruni-blog.pages.dev/db-17/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-17</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>대량 적재 직후 추정 행 수가 실제와 크게 어긋나 옵티마이저가 중첩 루프 조인을 고르는 문제를 다뤄요. 통계를 보는 방식과 적재 뒤 ANALYZE, 치우친 컬럼의 표본 늘리기, CREATE STATISTICS 확장 통계, 임시 테이블 통계까지 정리했어요.</description>
    </item>
    <item>
      <title>인덱스가 있는데 안 타는 이유</title>
      <link>https://bruni-blog.pages.dev/db-16/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-16</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>인덱스가 있는데 EXPLAIN 에 순차 스캔이 뜨는 이유를 못 쓰는 경우와 안 쓰기로 한 경우로 나눠요. 컬럼에 씌운 함수, 암묵 형변환, 낡은 통계, 나쁜 선택도, 작은 테이블을 EXPLAIN ANALYZE 로 가려내는 순서와 힌트를 마지막에 써야 하는 이유를 정리했어요.</description>
    </item>
    <item>
      <title>대량 DELETE 가 복제를 무너뜨린다</title>
      <link>https://bruni-blog.pages.dev/db-15/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-15</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>천만 행을 DELETE 한 문장으로 지우면 WAL·바이너리 로그가 부풀고 복제본이 하나의 스레드로 재생하느라 복제 지연이 수십 분까지 벌어져요. 1초 안에 끝나는 배치로 나눠 지우기, 복제 지연 보며 멈추기, 남길 것만 복사하기, 파티셔닝을 정리했어요.</description>
    </item>
    <item>
      <title>소프트 삭제(deleted_at)가 느려지는 이유 — 부분 인덱스와 유니크 재설계</title>
      <link>https://bruni-blog.pages.dev/db-13/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-13</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>deleted_at 만 채우는 소프트 삭제는 지운 행이 인덱스와 캐시에 남아 조회가 점점 느려지고, 같은 이메일로 재가입하면 유니크 제약이 충돌해요. PostgreSQL 부분 인덱스, MySQL 생성 컬럼 우회, 보존 기간 뒤 실제 삭제로 푸는 법을 정리했어요.</description>
    </item>
    <item>
      <title>서머타임에 배치가 두 번 돌거나 건너뛴다</title>
      <link>https://bruni-blog.pages.dev/db-12/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-12</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>서머타임이 시작되는 날엔 로컬 시각이 사라져 크론 배치가 건너뛰고, 끝나는 날엔 같은 시각이 두 번 와서 두 번 돌아요. 해외 리포트를 받는 한국 서비스도 겪는 문제예요. UTC 스케줄, TIMESTAMPTZ 저장, 대상 기간 인자와 멱등 배치, tzdata 갱신을 정리했어요.</description>
    </item>
    <item>
      <title>REPEATABLE READ, MySQL 과 PostgreSQL 은 다르다 — 격리 수준</title>
      <link>https://bruni-blog.pages.dev/db-11/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-11</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>같은 REPEATABLE READ 라도 MySQL InnoDB 는 읽기만 스냅샷이고 쓰기는 최신 값을 보며, PostgreSQL 은 충돌하면 직렬화 실패로 끝나요. DB 별 기본 격리 수준과 READ COMMITTED 의 문장 단위 스냅샷을 정리했어요.</description>
    </item>
    <item>
      <title>안 쓰는 인덱스 찾는 법 — pg_stat_user_indexes 로 지워도 되는지 판단하기</title>
      <link>https://bruni-blog.pages.dev/db-08/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-08</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>인덱스·쿼리 성능</category>
      <description>인덱스가 많으면 INSERT 가 느려지고 캐시·청소 비용도 늘어요. pg_stat_user_indexes 의 idx_scan 으로 안 쓰는 인덱스를 찾을 때 stats_reset·복제본·유니크 인덱스를 먼저 볼 이유와 MySQL INVISIBLE 인덱스 활용을 정리했어요.</description>
    </item>
    <item>
      <title>운영 중 인덱스 추가 — CREATE INDEX CONCURRENTLY 로 쓰기 막지 않기</title>
      <link>https://bruni-blog.pages.dev/db-07/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-07</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>일반 CREATE INDEX 는 인덱스가 다 만들어질 때까지 INSERT·UPDATE·DELETE 를 막아요. CONCURRENTLY 가 테이블을 두 번 훑으며 쓰기를 허용하는 방식과 실패하면 남는 INVALID 인덱스 점검, MySQL 온라인 DDL 비교를 정리했어요.</description>
    </item>
    <item>
      <title>pgbouncer transaction 모드가 깨는 prepared statement·SET</title>
      <link>https://bruni-blog.pages.dev/db-06/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=db-06</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>트랜잭션·락·DB 운영</category>
      <description>pgbouncer 를 transaction 모드로 바꾸면 트랜잭션마다 다른 백엔드를 받아 세션에 붙인 것이 깨져요. prepared statement 에러, 사라지는 SET search_path, 세션 어드바이저리 락을 푸는 법과 버전 1.21 의 변화를 정리했어요.</description>
    </item>
    <item>
      <title>서비스 목표(SLO)는 장애 전에 정한다 — 기준 문장과 에러 버짓</title>
      <link>https://bruni-blog.pages.dev/backend-42/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=backend-42</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>배포·관측</category>
      <description>장애 중에 무엇을 볼지부터 논의하면 판단이 늦고 기준이 흔들려요. 대상·측정 위치·성공 정의·기준·기간을 갖춘 목표 문장(예: 30일 동안 99% 요청이 800ms 이하)과 사용자 관점 지표, 1% 여유분을 배포 속도의 근거로 쓰는 법을 정리했어요.</description>
    </item>
    <item>
      <title>기능(피처) 플래그는 지우지 않으면 부채가 된다 — 정리 규칙</title>
      <link>https://bruni-blog.pages.dev/backend-41/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=backend-41</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>배포·관측</category>
      <description>2년 만에 기능 플래그가 200개로 늘어 무엇이 켜졌는지 아무도 모르는 상황을 다뤄요. 만들 때 목적·주인·만료일·종류를 기록하기, 임시 플래그와 영구 스위치 나누기, 30일 넘게 100%·0% 인 플래그 찾기, 정기적으로 지우는 자리 만들기를 정리했어요.</description>
    </item>
    <item>
      <title>카나리 배포가 못 잡는 장애 5가지</title>
      <link>https://bruni-blog.pages.dev/backend-40/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=backend-40</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>배포·관측</category>
      <description>카나리에서 30분 지켜보고 통과했는데 전체 확대 뒤 터지는 건 카나리가 소수 트래픽·짧은 시간에 드러나는 문제만 잡기 때문이에요. 부하·누수·드문 경로·데이터 오염·전체에서만 나는 문제를 단계적 확대와 넓은 관찰 지표로 덮는 법을 정리했어요.</description>
    </item>
    <item>
      <title>샘플링이 장애 요청만 버린다 — 꼬리 샘플링(tail sampling)</title>
      <link>https://bruni-blog.pages.dev/backend-39/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=backend-39</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>배포·관측</category>
      <description>추적을 1% 무작위로 샘플링하면 정상 요청은 충분히 남고 정작 드문 실패 요청은 사라져요. 요청이 끝난 뒤 결과를 보고 고르는 방식, 오류·느린 요청 전부 남기기, 엔드포인트별 최소 건수 보장, 샘플링 결정을 문맥에 실어 전파하기를 정리했어요.</description>
    </item>
    <item>
      <title>로그는 많은데 못 찾는다 — 구조화 로그와 trace_id</title>
      <link>https://bruni-blog.pages.dev/backend-38/</link>
      <guid isPermaLink="false">https://bruni-world.pages.dev/blog/post?p=backend-38</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>배포·관측</category>
      <description>로그는 초당 수천 줄인데 장애 때 원하는 요청을 못 찾는 건 형식이 제각각이고 이어 볼 식별자가 없어서예요. 필드로 남기는 구조화 로그, 미들웨어로 trace_id 자동 부착, 판단 근거가 된 값 담기, 개인정보 빼기, 보관 기간 정하기를 정리했어요.</description>
    </item>
  </channel>
</rss>
