<?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>Today I Learned on Kelly Dev</title><link>https://kelly-chui.github.io/til/</link><description>Recent content in Today I Learned on Kelly Dev</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Tue, 18 Aug 2026 23:30:00 +0900</lastBuildDate><atom:link href="https://kelly-chui.github.io/til/index.xml" rel="self" type="application/rss+xml"/><item><title>TIL. Aug 18, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-18/</link><pubDate>Tue, 18 Aug 2026 23:30:00 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-18/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stack Day
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LocalDay&lt;/code&gt; 날짜 모델 도입&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Clock&lt;/code&gt;과 &lt;code&gt;FixedClock&lt;/code&gt; 추가&lt;/li&gt;
&lt;li&gt;완료 기록·취소·보관·삭제 UseCase를 날짜 모델에 맞게 수정&lt;/li&gt;
&lt;li&gt;&lt;code&gt;InMemoryHabitRepository&lt;/code&gt;, &lt;code&gt;InMemoryCompletionRepository&lt;/code&gt; 구현 및 테스트 추가&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-localday-time-boundary/"&gt;StackDay. Date로 하루를 표현하면 생기는 문제&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="localday-도입하기"&gt;LocalDay 도입하기&lt;/h3&gt;
&lt;p&gt;Stack Day에서는 &lt;code&gt;Date&lt;/code&gt; 하나로 특정 시점과 특정 날짜를 모두 표현하고 있었다. 그래서 달력상의 날짜만 필요한 값을 &lt;code&gt;LocalDay&lt;/code&gt;로 분리했다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LocalDay&lt;/code&gt;: &lt;code&gt;startedOn&lt;/code&gt;, &lt;code&gt;archivedOn&lt;/code&gt;, &lt;code&gt;completedOn&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Date&lt;/code&gt;: &lt;code&gt;createdAt&lt;/code&gt;, &lt;code&gt;updatedAt&lt;/code&gt;, &lt;code&gt;recordedAt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;현재 시각은 &lt;code&gt;Clock&lt;/code&gt;이 제공하고, 그 시각을 어느 날짜로 해석할지는 TimeZone이 결정하도록 분리했다. 전체 설계와 구현 코드는 &lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-localday-time-boundary/"&gt;개발일지&lt;/a&gt;에 정리했다.&lt;/p&gt;</description></item><item><title>TIL. Aug 17, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-17/</link><pubDate>Mon, 17 Aug 2026 23:30:00 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-17/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PS
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-1563-stone-game-v/"&gt;LeetCode 1563. Stone Game V&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;WWDC
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/wwdc-swift-concurrency-explore-structured-concurrency-in-swift-2/"&gt;Swift Concurrency. Explore Structured Concurrency in Swift (2) - WWDC21&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;마이그레이션
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/cs-algorithm-kadanes-algorithm/"&gt;Algorithm. Kadane&amp;rsquo;s Algorithm&lt;/a&gt; 마이그레이션&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/mibangmurok-dev-log-colorpicker/"&gt;미방문록. 대표 색상 추출 Picker 만들기&lt;/a&gt; 마이그레이션&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="unstructured-task"&gt;Unstructured Task&lt;/h3&gt;
&lt;p&gt;WWDC21 Explore Structured Concurrency in Swift 세션을 정리를 마무리했다.&lt;/p&gt;
&lt;p&gt;1편과 다르게 구조화된 task tree에 속하지 않는 unstructured task와 detached task를 정리했다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Task { ... }&lt;/code&gt;로 만든 unstructured task는 생성한 scope가 끝나도 계속 실행될 수 있다. 생성 지점의 actor, priority, task-local value를 상속한다.&lt;/p&gt;</description></item><item><title>TIL. Aug 16, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-16/</link><pubDate>Sun, 16 Aug 2026 23:30:00 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-16/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PS
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-1360d-buying-shovels/"&gt;Codeforces 1360D. Buying Shovels&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Stack Day
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CancelCompletionUseCase&lt;/code&gt;, &lt;code&gt;ArchiveHabitUseCase&lt;/code&gt;, &lt;code&gt;DeleteHabitUseCase&lt;/code&gt; 구현&lt;/li&gt;
&lt;li&gt;완료 기록 삭제 테스트와 공통 테스트 Repository 정리&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-completion-identity/"&gt;StackDay. 완료 기록을 취소할 때 무엇을 삭제해야 할까&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="in-memory-repository와-테스트-용도-repository"&gt;in-memory Repository와 테스트 용도 Repository&lt;/h3&gt;
&lt;p&gt;프로덕션의 In-Memory Repository는 실제 저장 상태를 다루고, 테스트용 Repository는 호출과 오류를 관찰하는 Test Double이다. 같은 형태로 보이더라도 목적이 달라 분리했다.&lt;/p&gt;
&lt;h3 id="id와-business-key"&gt;ID와 Business Key&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Completion.ID&lt;/code&gt;는 기록 자체를 식별하고, &lt;code&gt;(habitID, completedOn)&lt;/code&gt;은 현재 정책에서 해당 날짜의 기록을 찾는 조건으로 분리했다. 없는 기록 취소를 성공으로 넘기지 않은 이유까지 &lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-completion-identity/"&gt;개발일지&lt;/a&gt;에 정리했다.&lt;/p&gt;</description></item><item><title>TIL. Aug 15, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-15/</link><pubDate>Sat, 15 Aug 2026 23:30:00 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-15/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PS
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-276c-little-girl-and-maximum-sum/"&gt;Codeforces 276C. Little Girl and Maximum Sum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3702-longest-subsequence-with-non-zero-bitwise-xor/"&gt;LeetCode 3702. Longest Subsequence With Non-Zero Bitwise XOR&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/wwdc-swift-concurrency-explore-structured-concurrency-in-swift-1/"&gt;Swift Concurrency. Explore Structured Concurrency in Swift (1) - WWDC21&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="structured-concurrency"&gt;Structured Concurrency&lt;/h3&gt;
&lt;p&gt;Explore Structured Concurrency in Swift WWDC 세션을 봤다.&lt;/p&gt;
&lt;p&gt;Meet async/await in Swift 세션도 마찬가지고, 이번 세션을 보면서 느낀 것은 Swift Concurrency의 중요한 컨셉은 비동기 코드를 일반적인 동기 코드와 비슷한 흐름으로 작성할 수 있게 하는 것이라고 생각했다.&lt;/p&gt;
&lt;p&gt;async/await가 에러 핸들링과 같은 부분을 비동기 코드도 동기 코드와 비슷하게 사용할 수 있게 해줬다면, Structured Concurrency는 조건문이나 루프같은 제어 흐름도 동기 코드와 비슷하게 사용하게 해준다.&lt;/p&gt;</description></item><item><title>TIL. Aug 14, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-14/</link><pubDate>Fri, 14 Aug 2026 23:30:00 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-14/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PS
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-550a-two-substrings/"&gt;Codeforces 550A. Two Substrings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3090-maximum-length-substring-with-two-occurrences/"&gt;LeetCode 3090. Maximum Length Substring With Two Occurrences&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Stack Day
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HabitRepository&lt;/code&gt;, &lt;code&gt;CompletionRepository&lt;/code&gt; 인터페이스 추가&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CreateHabitUseCase&lt;/code&gt;와 &lt;code&gt;RecordCompletionUseCase&lt;/code&gt; 구현&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-usecase-entity-responsibilities/"&gt;StackDay. UseCase와 Entity는 각각 어디까지 책임져야 할까&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-repository-contracts/"&gt;StackDay. Repository의 save를 insert와 update로 나눈 이유&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="usecase와-entity의-책임"&gt;UseCase와 Entity의 책임&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;CreateHabitUseCase&lt;/code&gt;와 &lt;code&gt;RecordCompletionUseCase&lt;/code&gt;를 구현하면서, Entity가 스스로 유효한 상태를 보장하고 UseCase는 객체를 조합해 작업 흐름을 만드는 쪽으로 책임을 나눴다.&lt;/p&gt;
&lt;p&gt;이름 정규화와 유효성 검증은 &lt;code&gt;Habit&lt;/code&gt;에, 저장 순서와 중복 확인은 UseCase에 뒀다. 자세한 고민은 &lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-usecase-entity-responsibilities/"&gt;개발일지&lt;/a&gt;에 정리했다.&lt;/p&gt;</description></item><item><title>TIL. Aug 13, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-13/</link><pubDate>Thu, 13 Aug 2026 21:30:00 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-13/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/cs-data-structure-segment-tree/"&gt;Data Structure. Segment Tree&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-2213-longest-substring-of-one-repeating-character/"&gt;LeetCode 2213. Longest Substring of One Repeating Character&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-separating-responsibility-and-types/"&gt;StackDay. 책임 분리와 타입 분리&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="stackday-통계-계산"&gt;StackDay 통계 계산&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;HabitStatistics&lt;/code&gt;를 구현하면서 계산 결과를 표현하는 타입과 계산 로직을 분리했다. 다만 &lt;code&gt;HabitStatisticsCalculator&lt;/code&gt;가 &lt;code&gt;HabitStreakCalculator&lt;/code&gt;에 의존하게 되면서, 여러 Calculator가 같은 날짜 정규화와 완료 기록 필터링을 반복하는 문제가 보였다.&lt;/p&gt;
&lt;p&gt;타입을 나누는 것만으로 항상 구조가 좋아지는 것은 아니고, 공유하는 계산 맥락까지 함께 살펴봐야 한다는 점을 배웠다. 자세한 고민은 &lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-separating-responsibility-and-types/"&gt;StackDay 개발일지&lt;/a&gt;에 정리했다.&lt;/p&gt;</description></item><item><title>TIL. Aug 12, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-12/</link><pubDate>Wed, 12 Aug 2026 23:30:00 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-12/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-2958-length-of-longest-subarray-with-at-most-k-frequency/"&gt;LeetCode 2958. Length of Longest Subarray With at Most K Frequency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-2996-smallest-missing-integer-greater-than-sequential-prepix-sum/"&gt;LeetCode 2996. Smallest Missing Integer Greater Than Sequential Prefix Sum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/stackday-dev-log-derived-value-responsibility/"&gt;StackDay. 엔티티와 계산 책임 분리하기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="파생-값을-구현할-때의-책임-분리"&gt;파생 값을 구현할 때의 책임 분리&lt;/h3&gt;
&lt;p&gt;StackDay의 &lt;code&gt;HabitEntry&lt;/code&gt;와 &lt;code&gt;HabitStreak&lt;/code&gt;을 구현했다. 모델링 단계에서 정의한 파생 값을 실제 코드로 옮기면서, 값을 표현하는 타입과 값을 계산하는 로직을 분리했다.&lt;/p&gt;
&lt;p&gt;AI 에이전트가 작성한 내용중에 별로인 것들을 몇개 직접 수정했는데 리스트로 정리하면 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HabitEntry&lt;/code&gt;의 이니셜라이저 전체 &lt;code&gt;Completion&lt;/code&gt; 목록을 직접 탐색하고, 생성 실패/성공을 판정했다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HabitStreak&lt;/code&gt;의 이니셜라이저 내부에 &lt;code&gt;Streak&lt;/code&gt; 계산 로직이 들어있었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;둘 다 경계가 제대로 구분되지 않았다. &lt;code&gt;HabitEntry&lt;/code&gt; 내부에서 전체 &lt;code&gt;Completion&lt;/code&gt;을 탐색하면서 조건에 맞는 &lt;code&gt;Completion&lt;/code&gt;을 찾아내는건 비효율적이기도 하고, 이건 유즈케이스에서 해야 될 일이다.&lt;/p&gt;</description></item><item><title>TIL. Aug 10, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-10/</link><pubDate>Mon, 10 Aug 2026 23:42:07 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-10/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;devbox-light-server
&lt;ul&gt;
&lt;li&gt;Docker 이미지 작성 및 컨테이너 실행&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.data&lt;/code&gt; 볼륨 연결과 healthcheck 추가&lt;/li&gt;
&lt;li&gt;GitHub Actions에서 테스트 이후 이미지를 빌드하도록 구성&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main&lt;/code&gt; 브랜치에 push하면 GHCR에 Docker 이미지를 자동으로 배포하도록 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PS
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-1510-stone-game-iv/"&gt;LeetCode 1510&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-1140-stone-game-ii/"&gt;LeetCode 1140&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="stone-game의-승패-dp"&gt;Stone Game의 승패 DP&lt;/h3&gt;
&lt;h4 id="leetcode-1510"&gt;LeetCode 1510&lt;/h4&gt;
&lt;p&gt;Stone Game 시리즈는 현재 플레이어가 이길 수 있는지를 상태로 두고 풀면 된다. Alice가 먼저 시작하는 것은 고정되어 있으므로, Alice와 Bob을 따로 나누기보다 현재 차례의 플레이어 기준으로 생각하는 편이 자연스럽다.&lt;/p&gt;</description></item><item><title>TIL. Aug 9, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-09/</link><pubDate>Sun, 09 Aug 2026 22:16:51 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-09/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;dev-data-server-light
&lt;ul&gt;
&lt;li&gt;DB, Auth Token, Storage에 JSON 기반 영속성 추가&lt;/li&gt;
&lt;li&gt;JSON 파일 읽기·쓰기 로직 공통화&lt;/li&gt;
&lt;li&gt;실행 환경에 따라 JSON과 in-memory 저장소를 선택하도록 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Stack Day
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Habit&lt;/code&gt;, &lt;code&gt;Habit Entry&lt;/code&gt;, &lt;code&gt;Completion&lt;/code&gt;의 역할을 나눠 데이터 모델링&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="저장-방식은-애플리케이션의-관심사가-아니다"&gt;저장 방식은 애플리케이션의 관심사가 아니다&lt;/h3&gt;
&lt;p&gt;dev-data-server-light를 처음 만들 때는 in-memory 저장소만 사용했다. 개발 중에는 빠르고 편하지만 서버를 재시작하면 유저, 토큰, 파일 데이터가 모두 사라진다. MVP를 마무리하려면 실제로 재시작해도 데이터가 남는 저장 방식이 필요했다.&lt;/p&gt;</description></item><item><title>TIL. Aug 8, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-08/</link><pubDate>Sat, 08 Aug 2026 21:38:24 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-08/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PS
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3302-find-the-lexicographically-smallest-valid-sequence/"&gt;LeetCode 3302&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-1294c-product-of-three-numbers/"&gt;Codeforces 1294C&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Stack Day의 컨셉과 MVP 범위 다시 정리&lt;/li&gt;
&lt;li&gt;기존에 작성하던 Stack Day 코드를 정리하고, 다음 구현을 위한 기준 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="leetcode-3302와-cpu-스케줄링"&gt;LeetCode 3302와 CPU 스케줄링&lt;/h3&gt;
&lt;p&gt;문제를 보면서 예전에 풀었던 CPU 스케줄링 문제가 연상됐다. CPU 스케줄링은 현재 들어온 작업만 보고 결정하면 최적의 결과를 만들기 어렵고, 앞으로 어떤 작업이 들어올지까지 알아야 한다.&lt;/p&gt;
&lt;p&gt;LeetCode 3302도 현재 인덱스에서 문자를 고를 때 뒤에 어떤 문자들이 남아 있는지를 알아야 했다. 실제 배열은 한 번에 주어지므로 미래를 기다릴 필요는 없지만, 인덱스 포인터의 시점에서는 뒤쪽 정보를 미리 알고 있어야 한다.&lt;/p&gt;</description></item><item><title>TIL. Aug 7, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-07/</link><pubDate>Fri, 07 Aug 2026 22:07:31 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-07/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PS
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-459b-pashmak-and-flowers/"&gt;Codeforces 459B&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;dev-data-server-light
&lt;ul&gt;
&lt;li&gt;Auth 기능 추가&lt;/li&gt;
&lt;li&gt;에이전트 설정 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;블로그 클론 이후 Mermaid 재설치와 &lt;code&gt;npm audit&lt;/code&gt; 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="ai-에이전트-설정-문서의-역할"&gt;AI 에이전트 설정 문서의 역할&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;, Rule, Workflow, Skill의 역할을 다시 정리했다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;: 프로젝트 구조, 아키텍처, 사용 기술처럼 항상 필요한 정보&lt;/li&gt;
&lt;li&gt;Rule: 프로젝트 전반에서 지켜야 하는 규칙&lt;/li&gt;
&lt;li&gt;Workflow: 반복 작업의 절차&lt;/li&gt;
&lt;li&gt;Skill: 특정 분야의 지식과 작업 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;모든 내용을 하나의 &lt;code&gt;AGENTS.md&lt;/code&gt;에 넣기보다, 에이전트가 현재 작업에 필요한 컨텍스트만 읽을 수 있도록 성격과 범위에 따라 나누는 편이 낫다.&lt;/p&gt;</description></item><item><title>TIL. Aug 6, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-06/</link><pubDate>Thu, 06 Aug 2026 22:58:30 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-06/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3345-smallest-divisible-digit-product-i/"&gt;LeetCode 3345&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-489c-given-length-and-sum-of-digits/"&gt;Codeforces 489C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;블로그 스크립트 구조화, &lt;code&gt;npm run&lt;/code&gt; 스크립트 정리&lt;/li&gt;
&lt;li&gt;StackDay 프로젝트 도메인, 데이터 모델, 유즈케이스, MVP 범위 정리&lt;/li&gt;
&lt;li&gt;Codex SKILL 공부&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="그리디-의심하기"&gt;그리디 의심하기&lt;/h3&gt;
&lt;p&gt;Codeforces 489C를 DP로 한참 구현하다가, 뒤늦게 그리디로 해결되는 문제라는 걸 알게 되었다.&lt;/p&gt;
&lt;p&gt;PS에서는 완전탐색 → 그리디 → DP 순서로 가능성을 검토하는 습관이 중요한 것 같다. 그리디가 최적인 것을 증명하는 연습이 더 필요하다는 것을 느꼈다. 경험을 통한 직관으로&amp;hellip;&lt;/p&gt;
&lt;h3 id="정책---도메인---데이터-모델---유즈케이스-순서로-사고하기"&gt;정책 -&amp;gt; 도메인 -&amp;gt; 데이터 모델 -&amp;gt; 유즈케이스 순서로 사고하기&lt;/h3&gt;
&lt;p&gt;Day Stack을 한번 뒤엎어야 했던 어제의 실패를 반면교사 삼아서, 이번엔 실제 구현에 들어가기 전에 도메인과 정책부터 제대로 잡으려 했다.&lt;/p&gt;</description></item><item><title>TIL. Aug 5, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-05/</link><pubDate>Wed, 05 Aug 2026 21:30:22 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-05/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3310-remove-methods-from-project/"&gt;LeetCode 3310&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-451b-sort-the-array/"&gt;Codeforces 451B&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stack day 코드 뒤엎기&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="swift-bfs에서-조금-더-쉽게-큐-사용하기"&gt;Swift BFS에서 조금 더 쉽게 큐 사용하기&lt;/h3&gt;
&lt;p&gt;Swift에서 BFS 문제를 풀 때, 대부분 함수로 분리하고, &lt;code&gt;struct Queue { ... }&lt;/code&gt; 처럼 헤더 포인터 변수를 사용하는 유사 큐를 만들어서 썼다.&lt;/p&gt;
&lt;div class="code-theme-github"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//... &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;bfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//... &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;오늘 LeetCode 3310번 문제를 풀면서, 방문 체크 배열을 외부에서도 확인해야 하는 문제여서 &lt;code&gt;inout&lt;/code&gt;으로 넘기기 보다는, BFS 로직을 인라인으로 쓰는 방법을 했는데, 생각해보니 큐도 그냥 BFS 로직 안에 인라인으로 쓰면 되지 않나 라는 생각이 들었다.&lt;/p&gt;</description></item><item><title>TIL. Aug 4, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-04/</link><pubDate>Tue, 04 Aug 2026 23:50:02 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-04/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3731-find-missing-elements/"&gt;LeetCode 3731&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-580c-kefa-and-park/"&gt;Codeforces 580c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;블로그 레이아웃, 숏코드, 콘텐츠, 스크립트, 기능 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ps"&gt;ps&lt;/h2&gt;
&lt;p&gt;Codeforces 580c가 그래프(트리)를 순회하는 문제였는데, 각 노드의 값이 0 혹은 1이라서 &lt;code&gt;bool&lt;/code&gt; 타입 벡터를 사용하고 입력을 받으려 했다.&lt;/p&gt;
&lt;div class="code-theme-github"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nl"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cin&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;아무런 이상이 없는 코드라고 생각했지만, 컴파일 에러가 생겼다. 이유를 조금 찾아보고 정리를 했는데 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;bool&lt;/code&gt; 타입을 원소로 가지는 벡터는 다른 벡터들과 다르게 각 원소를 1비트 단위로 압축해서 저장한다. (ex: &lt;code&gt;1010101...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;압축되어 저장되었기 때문에(그냥 비트에 녹아버렸으니까) 다른 타입의 벡터와 서브스크립트 접근 방식이 달라야 한다.&lt;/li&gt;
&lt;li&gt;이를 해결하기 위해서 프록시 객체가 존재한다. &lt;code&gt;a[3] = true;&lt;/code&gt; -&amp;gt; &lt;code&gt;a.operator[](3).operator=(true);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;만약 &lt;code&gt;bool&amp;amp;&lt;/code&gt;을 통해 레퍼런스를 뽑아내려 하면, 프록시 객체 자체가 리턴된다.&lt;/li&gt;
&lt;li&gt;결론적으로 &lt;code&gt;vector&amp;lt;bool&amp;gt;&lt;/code&gt;에선 위의 코드같은 문법을 못 쓴다&amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;위와 같은 경우가 아니더라도, 굳이 &lt;code&gt;bool&lt;/code&gt; 타입 벡터를 쓸 필요도 없는게, 프록시 객체가 원소를 뽑아오는 것도 다른 벡터보다 더 많은 계산 시간이 필요하다. 그래서 그냥 &lt;code&gt;int&lt;/code&gt; 벡터로 문제를 풀었다.&lt;/p&gt;</description></item><item><title>TIL. Aug 3, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-08-03/</link><pubDate>Mon, 03 Aug 2026 23:31:07 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-08-03/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;LeetCode 1406 Stone Game III&lt;/li&gt;
&lt;li&gt;Codeforces 520B Two Buttons&lt;/li&gt;
&lt;li&gt;WWDC &lt;code&gt;Meet async/await in Swift&lt;/code&gt; 세션 시청 및 정리.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="ps"&gt;PS&lt;/h3&gt;
&lt;p&gt;LeetCode 1406은 현재 차례인 플레이어가 상대보다 확보할 수 있는 최대 점수 차이를 DP로 정의해 풀었다. 누가 Alice인지 Bob인지에 따라 상태를 나누지 않아도, 현재 상태를 점수 차이로 표현하면 같은 점화식으로 문제를 풀 수 있다.&lt;/p&gt;
&lt;p&gt;점화식이 안떠올라서 힌트를 보고 풀었다.&lt;/p&gt;
&lt;p&gt;Codeforces 520B는 두 연산을 그래프의 간선으로 보고 BFS로 최단 거리를 구했다. 다만 목표값이 시작값보다 작을 때는 2배 연산이 도움이 되지 않으므로, 단순히 1씩 감소시키는 경우를 분리해 처리했다.&lt;/p&gt;</description></item><item><title>TIL. Jul 31, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-31/</link><pubDate>Fri, 31 Jul 2026 21:00:57 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-31/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;LeetCode 3016, LeetCode 1979 풀이&lt;/li&gt;
&lt;li&gt;Codeforces 455A 풀이&lt;/li&gt;
&lt;li&gt;AGENTS.md, SKILL.md 관련 자료 학습&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="ps"&gt;PS&lt;/h3&gt;
&lt;p&gt;LeetCode 3016은 3014와 풀이가 동일했다. 문제의 제약 조건은 달랐지만, 3014를 풀 당시 더 큰 제약까지 고려해서 구현해 두었던 덕분에 그대로 통과할 수 있었다. 왜인지 3014가 Easy 문제치고는 생각보다 까다로운 편이었다.&lt;/p&gt;
&lt;p&gt;Codeforces 455A는 전형적인 DP 문제였다. 다만 C++에서는 정수 범위를 고려해 &lt;code&gt;long long&lt;/code&gt;을 사용해야 하는데, Swift와 Python만 주로 사용하다 보니 이 부분을 자주 놓치는 것 같다.&lt;/p&gt;</description></item><item><title>TIL. Jul 30, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-30/</link><pubDate>Thu, 30 Jul 2026 23:19:17 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-30/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-279b-books/"&gt;Codeforces 279B&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3014-minimum-numbers-of-pushes-to-type-word-i/"&gt;LeetCode 3014&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;과거 Bicubic, Smart CCTV 프로젝트 정리&lt;/li&gt;
&lt;li&gt;미방문록 회의, AGENTS 수정.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="skill-사용하기"&gt;SKILL 사용하기&lt;/h3&gt;
&lt;p&gt;프로젝트를 진행하면서 기본적인 개발 원칙은 AGENTS.md에 정리했다. 하지만 View, ViewModel, Test처럼 반복해서 만드는 코드까지 모두 AGENTS.md에 작성하는 것은 적절하지 않았다.&lt;/p&gt;
&lt;p&gt;이런 작업은 프로젝트의 규칙이라기보다 반복 작업의 절차에 가깝기 때문이다.&lt;/p&gt;
&lt;p&gt;예를 들어 View를 생성할 때는 ViewModel을 어떻게 주입할지, Preview를 어떻게 작성할지 등 항상 비슷한 패턴을 따른다. ViewModel이나 테스트 코드도 마찬가지다.&lt;/p&gt;</description></item><item><title>TIL. Jul 29, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-29/</link><pubDate>Wed, 29 Jul 2026 20:53:29 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-29/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3518-smallest-palindromic-rearrangement-ii/"&gt;LeetCode 3518: Smallest Palindromic Rearrangement II&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-189a-cut-ribbon/"&gt;Codeforces 189A: Cut Ribbon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;블로그 깃 훅 제거&lt;/li&gt;
&lt;li&gt;블로그 스크립트 구조화&lt;/li&gt;
&lt;li&gt;블로그 커밋 목록 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="해결-내용"&gt;해결 내용&lt;/h2&gt;
&lt;p&gt;PS 두 문제를 푼 이후에, 블로그에서 스크립트와 깃 훅을 교체하고, 하루종일 깃과 씨름했다. Hugo 프로젝트의 커밋 로그가 너무 더러웠고, Squash, Rebase로 한 번 정리하려는데, 중간에 워킹 트리가 한번 꼬여버렸다.&lt;/p&gt;
&lt;h3 id="블로그-깃-훅-일시-제거"&gt;블로그 깃 훅 일시 제거.&lt;/h3&gt;
&lt;p&gt;블로그 깃 훅에는 두 가지 문제가 있다. 첫 번째는 타이밍 문제다. pre-commit에 뭔가 내용을 수정하는 훅을 넣으면, 커밋이 멈추지 않고. 변경사항을 유지한채로 커밋되어버린다.&lt;/p&gt;</description></item><item><title>TIL. Jul 28, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-28/</link><pubDate>Tue, 28 Jul 2026 21:09:14 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-28/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-230b-t-primes/"&gt;Codeforces 230B. T-Primes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3517-smallest-palindromic-rearrangement-i/"&gt;Leetcode 3517. Smallest Palindromic Rearrangement I&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="c-배열-vs-벡터"&gt;C++ 배열 vs 벡터&lt;/h3&gt;
&lt;p&gt;Codeforces에서는 C++로만 코드를 작성하는데, 최근에는 벡터보다 C 스타일 배열을 선호했다. 그런데 오늘 T-Primes 문제를 풀면서 다시 벡터를 쓸까 고민했다.&lt;/p&gt;
&lt;p&gt;가장 큰 이유는 보일러플레이트 때문이다. &lt;code&gt;push_back&lt;/code&gt; 같은 벡터에서 편리한, 다른 언어에서는 당연히 있는 메소드가 배열에 없다. 결국 추가 코드를 작성하고 어느정도의 비효율이 생긴다. 그 외에도 배열은 함수에 넘길 때 크기를 같이 넘겨줘야 하는 번거로움이 있다. 글로벌 변수를 선호하지 않아서 레퍼런스를 파라미터로 와르르 넘기는 스타일을 쓰는데, 배열이면 크기도 같이 들고 다녀야 한다.&lt;/p&gt;</description></item><item><title>TIL. Jul 27, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-27/</link><pubDate>Mon, 27 Jul 2026 21:32:08 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-27/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-4c-registration-system/"&gt;Codeforces 4C. Registration System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-codeforces-25a-iq-test/"&gt;Codeforces 25A. IQ Test&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;각각 Hash Table과 구현 능력을 요구하는 PS 문제였다. IQ Test 부분이 구현이 살짝 번거로운 부분이 있었다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/wwdc-swiftui-essentials/"&gt;SwiftUI. SwiftUI Essentials&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;WWDC 24에서 나온 SwiftUI Essentials 세션을 봤다. 24분 영상인데 정보 밀도가 엄청 높고 예제에서 보여준 것들도 많아서, 직접 예제를 돌리고 캡처하고, 동영상 녹화하고 하는데 꽤 시간이 들었다.&lt;/p&gt;
&lt;p&gt;덕분에 블로그에 이미지 수평 배열, 이미지 캡션과 같은 숏 코드들도 추가했다.&lt;/p&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="swiftui-essentials"&gt;SwiftUI Essentials&lt;/h3&gt;
&lt;p&gt;WWDC 세션을 하나 봤다. 이번에는 SwiftUI의 기본 구조를 다시 정리하는 내용이었는데, 핵심은 &lt;code&gt;View&lt;/code&gt;가 실제 UI 객체를 직접 만지는 대상이 아니라 선언형으로 UI를 설명하는 값이라는 점 이었다(Demystify SwiftUI도 마찬가지고 엄청나게 반복되는 내용이다.)&lt;/p&gt;</description></item><item><title>TIL. Jul 24, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-24/</link><pubDate>Fri, 24 Jul 2026 21:23:17 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-24/</guid><description>&lt;h2 id="키워드"&gt;키워드&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;XOR 비트연산&lt;/li&gt;
&lt;li&gt;Observation&lt;/li&gt;
&lt;li&gt;블로그 스크립트 정리, git hook&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="내용"&gt;내용&lt;/h2&gt;
&lt;h3 id="xor-연산"&gt;XOR 연산&lt;/h3&gt;
&lt;p&gt;LeetCode에 어제에 이어서 XOR 연산 문제가 나왔다. 일반적인 사칙연산과 다른 특징들을 사용해야하는 문제들이었다. 가장 큰 특징은 비트 연산은 비트 수가 고정되어 있어서 연산의 결과가 엄청나게 많은 경우의 수를 만들지 않는다.&lt;/p&gt;
&lt;p&gt;예를 들어서, 곱셉의 경우에는 $10^3$ 미만의 두 수를 곱하면 최대 999 * 999 = 약 100만이 되어서 거의 7자리수의 경우의 수가 되는데, 비트연산은 더 이상 자리수의 확장이 일어나지 않는다.&lt;/p&gt;</description></item><item><title>TIL. Jul 21, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-21/</link><pubDate>Tue, 21 Jul 2026 23:59:22 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-21/</guid><description>&lt;h2 id="키워드"&gt;키워드&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Codeforces 가입&lt;/li&gt;
&lt;li&gt;로컬 LLM opencode에 연결하고 ACP로 Xcode에 연동하기&lt;/li&gt;
&lt;li&gt;SwiftUI WWDC 세션, 특히 View Value와 View Identity&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="내용"&gt;내용&lt;/h2&gt;
&lt;h3 id="ps-풀기-codeforces-가입"&gt;PS 풀기, Codeforces 가입&lt;/h3&gt;
&lt;p&gt;LeetCode에서만 문제를 푸는게 조금 시야가 좁아지나 싶어서, Codeforces에 가입했다. Swift 지원이 없지만, PS 문제를 풀 때 특정 언어에 종속되지 않으려고 꾸준히 Swift, Python, C++를 돌아가면서 풀고 있으니 큰 문제는 없다.&lt;/p&gt;
&lt;p&gt;가장 풀이 수가 많은 문제 하나를 풀었다. 매일 LeetCode 오늘의 문제를 푸는 것이 루틴 중 하나인데, Codeforces, 삼성 SW Expert Academy 등 온라인 저지 사이트 여럿 돌아다니면서 풀어보려 한다. BOJ가 사라진 이후로 LeetCode 의존이 꽤 심해졌는데, 다양하게 풀어봐야겠다.&lt;/p&gt;</description></item><item><title>TIL. Jul 20, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-20/</link><pubDate>Mon, 20 Jul 2026 22:18:49 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-20/</guid><description>&lt;h2 id="키워드"&gt;키워드&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;단조 스택&lt;/li&gt;
&lt;li&gt;Hugo Flat Post -&amp;gt; Page Bundle&lt;/li&gt;
&lt;li&gt;블로그 스크립트는 어떤 언어로?&lt;/li&gt;
&lt;li&gt;Xcode 프로젝트명 바꾸기&lt;/li&gt;
&lt;li&gt;SwiftUI Identity&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="내용"&gt;내용&lt;/h2&gt;
&lt;h3 id="leetcode-1081-substring-subsequence-monotonic-stack"&gt;LeetCode 1081, Substring, Subsequence, Monotonic Stack&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-1081-smallest-subsequence-of-distinct-characters/"&gt;LeetCode 1081&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PS 문제를 풀면서, 처음에 Medium 문제인데 좀 해맸다, LCS 두 개를 하면서 Substring이랑 Subsequence 차이를 분명히 알았는데, Substring으로 생각하고 풀어서 스택을 써야 할 곳에 투 포인터를 썼다.&lt;/p&gt;
&lt;p&gt;단조 스택(Monotonic Stack) 문제인데, 사실 이런 스택이 있는지 오늘 처음 알았다. 그냥 스택은 스택으로 생각했으니까, 마치 Binary Search와 Parametric Search같은 느낌인가.&lt;/p&gt;</description></item><item><title>TIL. Jul 13, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-13/</link><pubDate>Mon, 13 Jul 2026 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-13/</guid><description>&lt;h2 id="키워드"&gt;키워드&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Python 로컬 변수 스코프.&lt;/li&gt;
&lt;li&gt;Python에서 람다식 정리, Swift 인라인 클로저와 다른점.&lt;/li&gt;
&lt;li&gt;블로그 마이그레이션 하면서 이전에 썼던 iOS 관련 글 복습&lt;/li&gt;
&lt;li&gt;블로그에서 카테고리를 몇개를 해야하는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="내용"&gt;내용&lt;/h2&gt;
&lt;h3 id="python-로컬-변수-스코프-문제"&gt;Python 로컬 변수 스코프 문제&lt;/h3&gt;
&lt;p&gt;Leetcode 1291번 문제를 푸는 도중에 다음과 같이 코드를 작성했다. 로직에 오류가 있어서 통과는 못하는 코드다.&lt;/p&gt;
&lt;div class="code-theme-github"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-py" data-lang="py"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sequentialDigits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;intSeq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;intSeq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;# 이부분&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;seq&lt;/code&gt; 변수가 &lt;code&gt;sequentialDigits&lt;/code&gt; 함수의 로컬 변수인데, &lt;code&gt;if&lt;/code&gt; 문 안의 &lt;code&gt;seq = []&lt;/code&gt; 부분 때문에 에러가 났다.&lt;/p&gt;</description></item><item><title>TIL. Jul 12, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-12/</link><pubDate>Sun, 12 Jul 2026 21:21:18 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-12/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Hugo 블로그에서 Mermaid를 외부 CDN 없이 렌더링하도록 변경&lt;/li&gt;
&lt;li&gt;Mermaid가 필요한 페이지에서만 스크립트를 로드하도록 최적화&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hugo --minify&lt;/code&gt;로 빌드 검증&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;p&gt;Mermaid 코드 블록은 &lt;code&gt;layouts/_markup/render-codeblock-mermaid.html&lt;/code&gt;에서 &lt;code&gt;&amp;lt;pre class=&amp;quot;mermaid&amp;quot;&amp;gt;&lt;/code&gt;로 변환하고, &lt;code&gt;layouts/_partials/extend_footer.html&lt;/code&gt;에서 Mermaid가 포함된 페이지에만 스크립트를 삽입하도록 구성했다.&lt;/p&gt;
&lt;p&gt;처음에는 ESM 파일 하나만 &lt;code&gt;static/&lt;/code&gt;에 복사했지만, 해당 파일이 내부 chunk를 추가로 참조하는 구조라 렌더링이 깨졌다. 브라우저가 다이어그램을 SVG로 바꾸지 못하고 원문 텍스트처럼 보여서, 의존성이 단순한 &lt;code&gt;mermaid.min.js&lt;/code&gt;로 교체했다.&lt;/p&gt;
&lt;p&gt;외부 CDN을 제거하는 작업도 단순히 파일을 내려받는 것으로 끝나지 않았다. 번들 파일의 의존성과 실행 방식까지 확인해야 실제 정적 사이트에서 안정적으로 동작한다는 것을 배웠다.&lt;/p&gt;</description></item><item><title>TIL. Jul 2, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-07-02/</link><pubDate>Thu, 02 Jul 2026 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-07-02/</guid><description>&lt;h1 id="요약"&gt;요약&lt;/h1&gt;
&lt;p&gt;오늘은 0-1 BFS를 문제에 적용해 보면서 알고리즘 선택의 중요성을 느꼈다. 또한 티스토리 블로그를 Hugo로 이전하기 위한 마이그레이션 스크립트를 작성하며 HTML을 Markdown으로 변환했다.&lt;/p&gt;
&lt;h2 id="배운-것"&gt;배운 것&lt;/h2&gt;
&lt;h3 id="0-1-bfs"&gt;0-1 BFS&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;LeetCode 3286. Find a Safe Walk Through a Grid&lt;/li&gt;
&lt;li&gt;사용 언어: Python, Swift&lt;/li&gt;
&lt;li&gt;사용 알고리즘: Dijkstra, 0-1 BFS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그동안은 거리 개념이 나오면 무조건 다익스트라를 사용했는데, 처음으로 0-1 BFS를 이용해서 문제를 풀었다. 같은 문제를 Python에서는 다익스트라로 풀었고. 0-1 BFS는 Swift로 풀었다.&lt;br&gt;
기존에 Swift에서 BFS를 사용할 때는 배열과 인덱스 포인터를 이용한 유사 Queue를 사용했는데, 이 방식으로는 큐의 헤드에 원소를 push하는 메소드를 구현하기 어려워서 배열을 사용했다. 문제의 제약조건이 널널해서 배열로 충분히 통과했는데, 어떻게 해야할지는 고민해봐야 할 것 같다. Linked List를 이용해서 큐를 만들면 되지만, 이게 힙와 다익스트라를 쓰는 것보다 코드를 작성하는 입장에서 효율적일지는 잘 모르겠다.&lt;/p&gt;</description></item><item><title>TIL. Jun 19, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-06-19/</link><pubDate>Fri, 19 Jun 2026 20:06:46 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-06-19/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;AGENTS.override.md&lt;/code&gt;의 적용 순서 정리&lt;/li&gt;
&lt;li&gt;전역 규칙과 프로젝트 규칙이 어떻게 병합되는지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;p&gt;규칙 파일은 전역에서 프로젝트 하위 디렉토리로 내려오면서 적용된다. 같은 디렉토리에서는 &lt;code&gt;AGENTS.override.md&lt;/code&gt;가 &lt;code&gt;AGENTS.md&lt;/code&gt;보다 우선하고, 하위 디렉토리의 규칙이 더 구체적인 지침으로 해석된다.&lt;/p&gt;
&lt;p&gt;결국 규칙은 전역에서 프로젝트 루트, 현재 작업 디렉토리 순서로 합쳐진다. 공통 원칙은 위쪽에 두고, 특정 모듈의 세부 규칙은 아래쪽에 두는 이유가 여기에 있다.&lt;/p&gt;
&lt;h2 id="해결-내용"&gt;해결 내용&lt;/h2&gt;
&lt;p&gt;전역 원칙은 전역 규칙에, 프로젝트 공통 원칙은 루트에, 모듈별 세부 지침은 하위 디렉토리에 두는 계층을 정리했다. 더 가까운 디렉토리의 규칙이 구체적인 지침으로 적용된다는 점도 확인했다.&lt;/p&gt;</description></item><item><title>TIL. Jun 17, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-06-17/</link><pubDate>Wed, 17 Jun 2026 21:52:31 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-06-17/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Antigravity의 Rules, Skills, Workflows 구조 정리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dev-data-server-light&lt;/code&gt;의 AGENTS 규칙을 새 구조에 맞춰 마이그레이션&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;p&gt;Antigravity의 핵심 구조는 다음처럼 정리할 수 있다.&lt;/p&gt;
&lt;div class="code-theme-github"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Rules = 행동 규칙
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Skills = 특정 분야의 지식과 노하우
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Workflows = 작업 절차&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Rules는 항상 지켜야 할 원칙을 정의하고, Skills는 Storage 설계나 코드 리뷰처럼 특정 작업에 필요한 전문 지식을 담는다. Workflows는 계획, 구현, 테스트처럼 작업을 어떤 순서로 진행할지 정의한다.&lt;/p&gt;
&lt;p&gt;기존 &lt;code&gt;AGENTS.md&lt;/code&gt;를 그대로 옮기는 것이 아니라, 공통 원칙과 모듈별 규칙을 분리해야 했다. 규칙을 작게 나누면 모든 작업에 불필요한 문맥을 주입하지 않으면서도 필요한 순간에 더 구체적인 지침을 적용할 수 있다.&lt;/p&gt;</description></item><item><title>TIL. Jun 16, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-06-16/</link><pubDate>Tue, 16 Jun 2026 20:29:07 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-06-16/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Antigravity IDE의 에이전트, 에디터, 터미널, 브라우저 구조 살펴보기&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/devbox-light-server-04-file-storage/"&gt;File Storage 구현 순서와 &lt;code&gt;StorageService&lt;/code&gt; 설계&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;p&gt;Antigravity는 에디터 안에서 에이전트가 작업을 수행하고, 브라우저와 터미널을 사용해 결과를 검증하는 개발 환경이다. Agent는 기능 개발이나 버그 수정처럼 실제 작업을 담당하고, Tab은 자동완성에 가깝다.&lt;/p&gt;
&lt;p&gt;File Storage는 먼저 계약을 만들고, 그 다음 &lt;code&gt;fs/promises&lt;/code&gt; 기반 구현체와 테스트를 추가한 뒤, Express와 분리된 Service를 얹는 순서로 진행하기로 했다. 처음부터 multipart 업로드까지 확장하지 않고, JSON과 단순한 파일 콘텐츠로 흐름을 검증하는 것도 중요한 범위 조절이었다.&lt;/p&gt;</description></item><item><title>TIL. Jun 11, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-06-11/</link><pubDate>Thu, 11 Jun 2026 21:36:55 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-06-11/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;LeetCode 3558 풀이&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/devbox-light-server-02-db-crud/"&gt;DB 모듈에서 capability와 use case 분리&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/devbox-light-server-04-file-storage/"&gt;File Storage 모듈의 계약과 서비스 설계&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;p&gt;기존에는 Route가 &lt;code&gt;Database&lt;/code&gt; 인터페이스를 직접 사용했다. 리팩터링 후에는 &lt;code&gt;Route -&amp;gt; DatabaseService -&amp;gt; RecordStore -&amp;gt; InMemoryRecordStore&lt;/code&gt; 흐름으로 바꾸었다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RecordStore&lt;/code&gt;는 레코드를 저장하고 꺼내는 교체 가능한 capability이고, &lt;code&gt;DatabaseService&lt;/code&gt;는 여러 저장소 동작을 조합하는 use case다. 예를 들어 &lt;code&gt;replace&lt;/code&gt; 이후 갱신된 레코드를 반환하거나, 삭제 결과에 따라 오류를 판단하는 흐름은 Service가 맡는다.&lt;/p&gt;
&lt;p&gt;File Storage도 같은 기준을 적용했다. 계약은 &lt;code&gt;key&lt;/code&gt;와 &lt;code&gt;Uint8Array&lt;/code&gt;만 사용해 작고 명시적으로 만들고, 로컬 파일 시스템이나 경로 검증은 구현체 안에 가둔다.&lt;/p&gt;</description></item><item><title>TIL. Jun 9, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-06-09/</link><pubDate>Tue, 09 Jun 2026 20:48:13 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-06-09/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;LeetCode 3689, 2574 풀이&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dev-data-server-light&lt;/code&gt;의 &lt;code&gt;AGENTS.md&lt;/code&gt; 구조 정리&lt;/li&gt;
&lt;li&gt;루트와 모듈별 개발 규칙의 중복 검토&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;p&gt;새 디렉토리 구조에서는 공통 원칙을 루트 &lt;code&gt;AGENTS.md&lt;/code&gt;에 모으고, 모듈에만 해당하는 규칙은 해당 모듈의 문서에 두는 방향이 적절하다.&lt;/p&gt;
&lt;p&gt;루트에는 TypeScript, Express, Vitest 같은 기술과 전체 아키텍처, 테스트 원칙을 둔다. 반면 DB 모듈의 레코드 모델이나 저장소 구현 규칙처럼 다른 모듈이 알 필요 없는 내용은 DB 문서에 남긴다.&lt;/p&gt;
&lt;p&gt;중복된 규칙은 단순히 길이의 문제가 아니다. 같은 내용이 여러 파일에 있으면 나중에 한쪽만 수정될 수 있고, AI가 서로 다른 지침으로 해석할 가능성도 생긴다.&lt;/p&gt;</description></item><item><title>TIL. Jun 8, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-06-08/</link><pubDate>Mon, 08 Jun 2026 21:04:28 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-06-08/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/devbox-light-server-00-concept/"&gt;&lt;code&gt;dev-data-server-light&lt;/code&gt;의 계층형 구조를 모듈형 구조로 바꾸는 작업 검토&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;가 새 디렉토리 구조와 충돌하지 않도록 정리&lt;/li&gt;
&lt;li&gt;Database, Route, Service의 책임 재검토&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;p&gt;기존 구조는 &lt;code&gt;routes&lt;/code&gt;, &lt;code&gt;services&lt;/code&gt;, &lt;code&gt;db&lt;/code&gt;처럼 계층별로 나뉘어 있었다. 새 구조에서는 모듈이 자신의 계약, 구현체, 서비스, 라우트를 함께 소유하도록 바꾸려 했다.&lt;/p&gt;
&lt;p&gt;계층형 구조에서는 &lt;code&gt;AGENTS.md&lt;/code&gt;에 각 계층의 역할을 적기 쉬웠지만, 모듈형 구조에서는 모듈의 책임과 공개 API를 기준으로 규칙을 작성해야 한다. 구조가 바뀌면 문서도 함께 바뀌어야 하며, 기존 규칙을 억지로 유지하면 오히려 AI가 잘못된 경계를 학습하게 된다.&lt;/p&gt;</description></item><item><title>TIL. Jun 4, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-06-04/</link><pubDate>Thu, 04 Jun 2026 20:17:42 +0900</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-06-04/</guid><description>&lt;h2 id="오늘-한-내용"&gt;오늘 한 내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kelly-chui.github.io/posts/devbox-light-server-02-db-crud/"&gt;&lt;code&gt;dev-data-server-light&lt;/code&gt;의 DB 모듈 설계 정리&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;System 모듈과 DB 인터페이스 구현 방향 검토&lt;/li&gt;
&lt;li&gt;저장소와 애플리케이션 로직의 경계 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="배운-내용"&gt;배운 내용&lt;/h2&gt;
&lt;h3 id="이름도-설계의-일부"&gt;이름도 설계의 일부&lt;/h3&gt;
&lt;p&gt;처음에는 &lt;code&gt;DocumentStore&lt;/code&gt;, &lt;code&gt;StoredDocument&lt;/code&gt;, &lt;code&gt;DocumentBody&lt;/code&gt;라는 이름을 사용했다. 하지만 &lt;a href="https://kelly-chui.github.io/posts/devbox-light-server-02-db-crud/"&gt;DB CRUD 인터페이스를 설계하는 과정&lt;/a&gt;에서 이 이름들이 프로젝트가 특정 Document Database를 전제로 한다는 인상을 준다는 것을 발견했다.&lt;/p&gt;
&lt;p&gt;In-Memory, SQL, JSON File 등 여러 구현을 염두에 둔다면 인터페이스도 구현 방식에서 자유로워야 한다. 그래서 &lt;code&gt;RecordStore&lt;/code&gt;, &lt;code&gt;StoredRecord&lt;/code&gt;, &lt;code&gt;RecordData&lt;/code&gt;처럼 더 중립적인 이름으로 바꿨다.&lt;/p&gt;</description></item><item><title>TIL. May 21, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-05-21/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-05-21/</guid><description>&lt;h1 id="요약"&gt;요약&lt;/h1&gt;
&lt;p&gt;LeetCode 문제를 풀면서 자료의 표현 방식이 성능에 큰 영향을 준다는 점을 다시 확인했다. 또한 Express의 &lt;code&gt;req&lt;/code&gt;, &lt;code&gt;res&lt;/code&gt;, &lt;code&gt;next()&lt;/code&gt;가 어떻게 협력하여 요청을 처리하는지 파이프라인 관점에서 정리했다.&lt;/p&gt;
&lt;h2 id="배운-것"&gt;배운 것&lt;/h2&gt;
&lt;h3 id="leetcode-3043-최적화"&gt;LeetCode 3043 최적화&lt;/h3&gt;
&lt;p&gt;LeetCode 3043번 문제를 풀었다. 두 정수형 배열에 있는 원소들 중 임의의 두 수를 선택했을 때, 공통의 일치하는 prefix의 최대 길이를 구하는 문제였다.&lt;/p&gt;
&lt;p&gt;우선, 각 배열의 길이가 최대 50000이기 때문에, 가능한 모든 쌍을 만들어서 크기를 구하는 방식으로 하면 시간복잡도가 O(n²)이 되어서 문제를 제 시간 안에 해결하기 힘들다. (n은 둘 중 긴 배열의 원소의 개수)&lt;/p&gt;</description></item><item><title>TIL. May 19, 2026</title><link>https://kelly-chui.github.io/til/2026/til-2026-05-19/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/til/2026/til-2026-05-19/</guid><description>&lt;h1 id="요약"&gt;요약&lt;/h1&gt;
&lt;p&gt;Express의 핵심 구성 요소와 요청 처리 흐름을 정리했다. 특히 Middleware가 특정 객체가 아니라 요청 처리 과정에서 동작하는 함수들의 역할이라는 점과, Express가 함수형 체인이 아닌 공유 객체(&lt;code&gt;req&lt;/code&gt;, &lt;code&gt;res&lt;/code&gt;)를 사용하는 파이프라인 구조라는 점을 이해하게 되었다.&lt;/p&gt;
&lt;h2 id="배운-것"&gt;배운 것&lt;/h2&gt;
&lt;h3 id="오늘-공부한-내용"&gt;오늘 공부한 내용&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Express의 App, Router, Middleware&lt;/li&gt;
&lt;li&gt;Express의 동작&lt;/li&gt;
&lt;li&gt;Express의 간단한 내부 구조&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="express의-핵심-구성-요소"&gt;Express의 핵심 구성 요소&lt;/h2&gt;
&lt;p&gt;처음에는 Express를 iOS의 MVC에서 View를 제거한 형태 정도로 생각했다. Route Handler가 Controller 역할을 하는 것이라고 생각했다.
Express를 구성하는 핵심 요소는 크게 다음과 같다.&lt;/p&gt;</description></item></channel></rss>