<?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>Software Architecture on Kelly Dev</title><link>https://kelly-chui.github.io/tags/software-architecture/</link><description>Recent content in Software Architecture on Kelly Dev</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Wed, 17 Jun 2026 21:52:31 +0900</lastBuildDate><atom:link href="https://kelly-chui.github.io/tags/software-architecture/index.xml" rel="self" type="application/rss+xml"/><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 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 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>SniffMEET. 여러 VIPER 구현에서 Router 구조 비교하기</title><link>https://kelly-chui.github.io/posts/sniffmeet-dev-log-viper-router-comparison/</link><pubDate>Tue, 12 Nov 2024 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/posts/sniffmeet-dev-log-viper-router-comparison/</guid><description>&lt;p&gt;VIPER에서 Router가 화면 전환을 담당한다는 원칙은 분명하다. 하지만 현재 화면을 어떻게 참조하는지, 다음 모듈은 누가 만드는지, AppRouter가 반드시 필요한지는 구현마다 달랐다.&lt;/p&gt;
&lt;p&gt;SniffMEET의 화면 구조를 정하기 전에 여러 VIPER 프로젝트를 비교하며 Router의 책임 범위를 확인했다.&lt;/p&gt;
&lt;h2 id="무엇을-확인했나"&gt;무엇을 확인했나&lt;/h2&gt;
&lt;p&gt;분석 기준은 다음 세 가지였다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Router가 현재 ViewController를 어떻게 참조하는가&lt;/li&gt;
&lt;li&gt;화면 전환 시 다음 VIPER 모듈을 누가 조립하는가&lt;/li&gt;
&lt;li&gt;여러 모듈에 걸친 전환을 AppRouter가 담당하는가&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="구현-비교"&gt;구현 비교&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구현&lt;/th&gt;
&lt;th&gt;모듈 조립&lt;/th&gt;
&lt;th&gt;화면 전환&lt;/th&gt;
&lt;th&gt;AppRouter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/amitshekhariitbhu/iOS-Viper-Architecture"&gt;iOS-Viper-Architecture&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;WireFrame의 정적 메서드&lt;/td&gt;
&lt;td&gt;출발 View를 인자로 전달&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/tailec/ios-architecture"&gt;ios-architecture&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;정적 팩토리 메서드&lt;/td&gt;
&lt;td&gt;전환 사례가 적음&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/ferranabello/Viperit"&gt;Viperit&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;프레임워크가 모듈을 관리&lt;/td&gt;
&lt;td&gt;모듈이 직접 자신을 표시&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AppModules&lt;/code&gt;로 모듈 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/giftbott/iOS-Architecture-Sample"&gt;iOS-Architecture-Sample&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;모듈별 생성&lt;/td&gt;
&lt;td&gt;앱 단위 Router가 화면 계층 관리&lt;/td&gt;
&lt;td&gt;싱글톤 AppRouter&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;구현은 달랐지만 공통점도 있었다. View나 Presenter가 직접 다음 화면을 생성하지 않았고, 화면 조립과 전환을 UI 바깥의 객체로 분리하고 있었다.&lt;/p&gt;</description></item></channel></rss>