<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog | SeungTaek Lim · namest504</title><link>https://namest504.github.io/blog/</link><description>SeungTaek Lim (namest504). Open-source contributions and writing about code and software projects.</description><language>ko-KR</language><lastBuildDate>Wed, 07 Oct 2026 21:00:00 +0900</lastBuildDate><atom:link href="https://namest504.github.io/index.xml" rel="self" type="application/rss+xml"/><item><title>가끔만 실패하는 테스트는 왜 생길까</title><link>https://namest504.github.io/blog/flaky-test-ordering/</link><pubDate>Wed, 07 Oct 2026 21:00:00 +0900</pubDate><guid>https://namest504.github.io/blog/flaky-test-ordering/</guid><description>&lt;p&gt;제 컴퓨터에서는 항상 통과하는데 CI에서는 가끔 실패하는 테스트가 있었습니다. 실패할 때 남는 말은 &lt;code&gt;missed message #0&lt;/code&gt; 한 줄이었습니다. 이 실패는 &lt;a href="https://github.com/apache/pulsar/issues/26683"&gt;apache/pulsar#26683&lt;/a&gt;에 정리해 두었습니다. 다시 받아야 할 message를 하나도 받지 못했다는 뜻입니다.&lt;/p&gt;</description></item><item><title>터미널은 어떻게 작업 표시줄에 진행률을 그릴까</title><link>https://namest504.github.io/blog/terminal-taskbar-progress/</link><pubDate>Wed, 30 Sep 2026 15:50:00 +0900</pubDate><guid>https://namest504.github.io/blog/terminal-taskbar-progress/</guid><description>&lt;p&gt;빌드를 걸어 두고 다른 창에서 일하다 보면 끝났는지 보려고 터미널을 자꾸 다시 열게 됩니다. 어떤 터미널에서는 작업 표시줄 아이콘에 초록색 막대가 차오르면서 진행 상황을 알려 줍니다. 그런데 제가 쓰는 Windows Terminal에서는 Gradle 빌드를 돌려도 이 막대가 나오지 않았습니다. 같은 불편을 적은 &lt;a href="https://github.com/gradle/gradle/issues/36282"&gt;issue&lt;/a&gt;도 이미 올라와 있었습니다.&lt;/p&gt;</description></item><item><title>executor를 닫으면 대기 중이던 작업은 어떻게 될까</title><link>https://namest504.github.io/blog/executor-shutdownnow-lost-future/</link><pubDate>Wed, 30 Sep 2026 10:30:00 +0900</pubDate><guid>https://namest504.github.io/blog/executor-shutdownnow-lost-future/</guid><description>&lt;p&gt;&lt;a href="https://github.com/apache/pulsar/pull/26672"&gt;다른 변경&lt;/a&gt;을 올리고 CI를 돌리던 중에 제 변경과 상관없는 테스트 하나가 시간 초과로 실패했습니다. 이 실패는 &lt;a href="https://github.com/apache/pulsar/issues/26685"&gt;apache/pulsar#26685&lt;/a&gt;에 정리해 두었습니다. 다시 돌려도 또 실패했습니다. client를 닫는 동안 계속 message를 보내는 테스트였습니다. 보낸 message 가운데 일부가 성공도 실패도 아닌 채로 영원히 끝나지 않고 있었습니다.&lt;/p&gt;</description></item><item><title>TableView에서 message 전체를 쓰고 싶을 때</title><link>https://namest504.github.io/blog/pulsar-tableview-message-mapper/</link><pubDate>Tue, 29 Sep 2026 21:00:00 +0900</pubDate><guid>https://namest504.github.io/blog/pulsar-tableview-message-mapper/</guid><description>&lt;p&gt;Pulsar의 &lt;code&gt;TableView&lt;/code&gt;는 topic을 key마다 최신 값 하나씩만 남긴 표처럼 보여 줍니다. 설정값이나 상태처럼 &amp;ldquo;지금 값&amp;quot;만 필요한 자료를 읽을 때 편합니다.&lt;/p&gt;</description></item><item><title>try-with-resources 안에서 쓰이지 않던 stream</title><link>https://namest504.github.io/blog/unused-stream-in-try-with-resources/</link><pubDate>Wed, 12 Nov 2025 22:10:00 +0900</pubDate><guid>https://namest504.github.io/blog/unused-stream-in-try-with-resources/</guid><description>&lt;p&gt;Spring Boot의 Gradle plugin을 두고 &lt;a href="https://github.com/spring-projects/spring-boot/issues/47883"&gt;issue&lt;/a&gt;가 올라와 있었습니다. 실행 가능한 jar를 만들 때 같은 파일을 필요한 것보다 한 번 더 열고 있다는 내용이었습니다. 코드를 보면 열어 놓고 아무 데도 쓰지 않는 stream이 하나 있었습니다.&lt;/p&gt;</description></item><item><title>JWT의 typ 값은 왜 대소문자를 가리면 안 될까</title><link>https://namest504.github.io/blog/jwt-typ-case-insensitive/</link><pubDate>Thu, 06 Nov 2025 21:30:00 +0900</pubDate><guid>https://namest504.github.io/blog/jwt-typ-case-insensitive/</guid><description>&lt;p&gt;Spring Security 버전을 올렸더니 잘 통과하던 JWT가 거부된다는 &lt;a href="https://github.com/spring-projects/spring-security/issues/18092"&gt;issue&lt;/a&gt;가 올라왔습니다. token은 그대로였고 header의 &lt;code&gt;typ&lt;/code&gt; 값을 검사하는 코드만 달라졌습니다. &lt;code&gt;at+jwt&lt;/code&gt;를 기대하는 곳에 &lt;code&gt;AT+JWT&lt;/code&gt;가 오면 실패했습니다.&lt;/p&gt;</description></item><item><title>OIDC 1: OAuth 2.0과 ID Token, 공개키 검증 이해하기</title><link>https://namest504.github.io/blog/tistory-112/</link><pubDate>Sat, 12 Jul 2025 21:29:52 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-112/</guid><description>&lt;h2 id="oauth-20에-인증을-더한-oidc"&gt;OAuth 2.0에 인증을 더한 OIDC&lt;/h2&gt;
&lt;p&gt;OIDC(OpenID Connect)는 OAuth 2.0 위에 인증 계층을 더한 프로토콜입니다. 차이를 이해하려고 먼저 OAuth 2.0의 범위를 살펴봤습니다.&lt;/p&gt;</description></item><item><title>Redis Lock으로 찜 토글 요청의 동시 접근 제어하기</title><link>https://namest504.github.io/blog/tistory-111/</link><pubDate>Sun, 17 Nov 2024 17:11:06 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-111/</guid><description>&lt;h2 id="같은-찜이-두-번-저장됐습니다"&gt;같은 찜이 두 번 저장됐습니다&lt;/h2&gt;
&lt;p&gt;찜 API는 하나였습니다. 이미 찜한 병원이면 취소하고 아니면 새로 추가하는 방식이었습니다. 찜 테이블에는 회원 ID와 병원 ID를 저장했습니다.&lt;/p&gt;</description></item><item><title>JPA 컬렉션 Fetch Join과 메모리 페이징 문제</title><link>https://namest504.github.io/blog/tistory-110/</link><pubDate>Sun, 10 Nov 2024 19:31:54 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-110/</guid><description>&lt;p&gt;N+1 쿼리를 줄이려고 연관 객체를 함께 조회했더니 다른 문제가 생겼습니다. 쿼리에서 페이지를 자르는 대신 메모리에서 페이징한다는 경고가 나왔습니다. 당시에는 단일 연관관계만 함께 조회하고 컬렉션에는 배치 조회를 적용하는 방향으로 바꿨습니다.&lt;/p&gt;</description></item><item><title>Fixture Monkey로 만든 객체의 필드가 null일 때</title><link>https://namest504.github.io/blog/tistory-109/</link><pubDate>Sun, 20 Oct 2024 01:34:25 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-109/</guid><description>&lt;h2 id="null을-만들지-않도록-했는데-npe가-발생했습니다"&gt;null을 만들지 않도록 했는데 NPE가 발생했습니다&lt;/h2&gt;
&lt;p&gt;Fixture Monkey로 테스트 객체를 생성하다가 NPE가 발생했습니다. &lt;code&gt;AnimalHospital&lt;/code&gt; 안에 있는 &lt;code&gt;HospitalInfo&lt;/code&gt;의 &lt;code&gt;name&lt;/code&gt;을 조회할 때였습니다. 객체 생성 코드에서 필요한 부분만 줄여 남긴 예시입니다.&lt;/p&gt;</description></item><item><title>CORS와 사전 요청: 브라우저가 다른 출처를 읽는 조건</title><link>https://namest504.github.io/blog/tistory-108/</link><pubDate>Sun, 06 Oct 2024 23:18:45 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-108/</guid><description>&lt;p&gt;“Eureka Client끼리 통신할 때도 CORS를 설정해야 하는가?”가 헷갈려 개념을 다시 정리했습니다. CORS는 브라우저가 다른 출처에 접근할 때 따르는 규칙입니다.&lt;/p&gt;</description></item><item><title>ObjectMapper가 LocalTime을 JSON으로 변환하지 못할 때</title><link>https://namest504.github.io/blog/tistory-106/</link><pubDate>Sat, 13 Jan 2024 01:21:48 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-106/</guid><description>&lt;h2 id="요청을-보내기-전에-변환이-실패했습니다"&gt;요청을 보내기 전에 변환이 실패했습니다&lt;/h2&gt;
&lt;p&gt;동물병원 운영 시간을 등록하는 MockMvc 테스트를 작성하고 있었습니다. 요일별로 시작 시간과 종료 시간을 넣은 요청 DTO를 만들고 JSON으로 변환해 보내는 코드입니다.&lt;/p&gt;</description></item><item><title>ReflectionTestUtils로 단위 테스트의 엔티티 ID 설정하기</title><link>https://namest504.github.io/blog/tistory-103/</link><pubDate>Sun, 19 Nov 2023 01:21:07 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-103/</guid><description>&lt;h2 id="작성자-확인에서-nullpointerexception이-발생했습니다"&gt;작성자 확인에서 NullPointerException이 발생했습니다&lt;/h2&gt;
&lt;p&gt;아래 코드는 질문 번호와 회원 번호를 받아 작성자가 같으면 질문을 삭제합니다.&lt;/p&gt;</description></item><item><title>Querydsl 페이징: PageImpl과 PageableExecutionUtils의 차이</title><link>https://namest504.github.io/blog/tistory-102/</link><pubDate>Tue, 14 Nov 2023 01:07:46 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-102/</guid><description>&lt;p&gt;아래 두 코드는 모두 페이징 결과를 반환합니다. 그런데 전체 개수를 구하는 방식에는 어떤 차이가 있을까요?&lt;/p&gt;
&lt;figure class="code-figure" data-code-block&gt;
&lt;figcaption class="code-head"&gt;&lt;span class="code-lang"&gt;Java&lt;/span&gt;&lt;span class="code-actions"&gt;&lt;span class="code-status" role="status" aria-live="polite"&gt;&lt;/span&gt;&lt;button class="code-copy" type="button" data-copy-code hidden&gt;Copy&lt;/button&gt;&lt;/span&gt;&lt;/figcaption&gt;
&lt;pre class="code-pre chroma" tabindex="0" aria-label="Java 코드"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="code-line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PageableExecutionUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pageable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;countQuery&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fetchOne&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;figure class="code-figure" data-code-block&gt;
&lt;figcaption class="code-head"&gt;&lt;span class="code-lang"&gt;Java&lt;/span&gt;&lt;span class="code-actions"&gt;&lt;span class="code-status" role="status" aria-live="polite"&gt;&lt;/span&gt;&lt;button class="code-copy" type="button" data-copy-code hidden&gt;Copy&lt;/button&gt;&lt;/span&gt;&lt;/figcaption&gt;
&lt;pre class="code-pre chroma" tabindex="0" aria-label="Java 코드"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="code-line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PageImpl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pageable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/figure&gt;
&lt;h2 id="마지막-페이지라면-개수를-추론할-수-있습니다"&gt;마지막 페이지라면 개수를 추론할 수 있습니다&lt;/h2&gt;
&lt;p&gt;전체 데이터가 24개이고 페이지 크기가 10이라고 가정했습니다. 첫째와 둘째 페이지에는 각각 10개가 들어가서 결과가 페이지를 꽉 채웁니다. 그래서 이 두 페이지 결과만으로는 전체 개수가 나오지 않습니다.&lt;/p&gt;</description></item><item><title>DataJpaTest에서 생성일이 null로 조회될 때</title><link>https://namest504.github.io/blog/tistory-101/</link><pubDate>Mon, 13 Nov 2023 17:13:51 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-101/</guid><description>&lt;h2 id="생성일만-비어-있었습니다"&gt;생성일만 비어 있었습니다&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Question&lt;/code&gt;에 생성·수정 시각을 담는 &lt;code&gt;AuditEntity&lt;/code&gt;를 포함했습니다. 빌더로 질문을 만들 때 &lt;code&gt;AuditEntity&lt;/code&gt;도 함께 생성하도록 해 두었습니다. 아래는 당시 필요한 부분만 발췌한 코드입니다.&lt;/p&gt;</description></item><item><title>Facade로 답변 생성 로직의 의존성 분리하기</title><link>https://namest504.github.io/blog/tistory-99/</link><pubDate>Wed, 08 Nov 2023 17:02:20 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-99/</guid><description>&lt;p&gt;&lt;a href="https://code-list.tistory.com/98"&gt;이전 글&lt;/a&gt;에서는 기존 코드를 리팩터링했습니다. 회원 조회, 질문 조회, 답변 저장은 메서드 하나가 모두 맡고 있었습니다. 이번에는 그 메서드를 나누고 호출하는 쪽에서는 과정을 간단하게 볼 수 있도록 정리했습니다.&lt;/p&gt;</description></item><item><title>Docker에서 Eureka Client가 접근할 수 없는 IP로 등록됐을 때</title><link>https://namest504.github.io/blog/tistory-97/</link><pubDate>Tue, 07 Nov 2023 00:41:19 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-97/</guid><description>&lt;p&gt;Eureka에 클라이언트를 등록하고 Spring Cloud Gateway에서 로드 밸런싱하도록 설정했습니다. 서버의 클라이언트 목록에는 이상이 없어 보였지만 Gateway를 통한 요청은 동작하지 않았습니다. IP 주소로 직접 요청하면 정상적으로 전달되는 상태였습니다.&lt;/p&gt;</description></item><item><title>H2 Console 화면이 X-Frame-Options에 막혔을 때</title><link>https://namest504.github.io/blog/tistory-96/</link><pubDate>Mon, 06 Nov 2023 20:35:29 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-96/</guid><description>&lt;p&gt;내장 H2 데이터베이스의 콘솔에 접속하려는데 화면이 정상적으로 표시되지 않았습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://namest504.github.io/blog/img/tistory/96-1.png" alt="H2 Console에 접속했지만 내용이 표시되지 않는 화면" loading="lazy"&gt;&lt;/p&gt;</description></item><item><title>LeetCode 133: 방문한 노드를 기억하며 그래프 복사하기</title><link>https://namest504.github.io/blog/tistory-94/</link><pubDate>Fri, 15 Sep 2023 14:57:24 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-94/</guid><description>&lt;h2 id="원본과-복제-노드를-짝지어-둡니다"&gt;원본과 복제 노드를 짝지어 둡니다&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://namest504.github.io/blog/img/tistory/94-1.png" alt="Clone Graph 문제와 그래프 예시" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;주어진 그래프를 복사하는 문제입니다. 당시에는 깊이 우선 탐색(DFS)으로 이웃 노드를 따라가면서 복제한 노드를 해시맵에 저장하는 방식으로 풀었습니다.&lt;/p&gt;</description></item><item><title>LeetCode 208: 단어와 접두사를 구분하는 Trie 구현</title><link>https://namest504.github.io/blog/tistory-93/</link><pubDate>Tue, 12 Sep 2023 01:35:17 +0900</pubDate><guid>https://namest504.github.io/blog/tistory-93/</guid><description>&lt;h2 id="경로가-있다고-단어인-것은-아닙니다"&gt;경로가 있다고 단어인 것은 아닙니다&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://namest504.github.io/blog/img/tistory/93-1.png" alt="Implement Trie의 생성, 삽입, 검색 요구사항" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;트라이(Trie)를 구현하는 문제입니다. 트라이는 문자열을 문자 단위로 저장합니다. 필요한 동작은 객체 생성, 단어 삽입, 단어 검색, 접두사 검색입니다.&lt;/p&gt;</description></item></channel></rss>