<?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>Repository on Kelly Dev</title><link>https://kelly-chui.github.io/tags/repository/</link><description>Recent content in Repository on Kelly Dev</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 16 Aug 2026 15:23:36 +0900</lastBuildDate><atom:link href="https://kelly-chui.github.io/tags/repository/index.xml" rel="self" type="application/rss+xml"/><item><title>StackDay. 비즈니스 규칙과 Entity Identity 분리하기</title><link>https://kelly-chui.github.io/posts/stackday-dev-log-completion-identity/</link><pubDate>Sun, 16 Aug 2026 15:23:36 +0900</pubDate><guid>https://kelly-chui.github.io/posts/stackday-dev-log-completion-identity/</guid><description>&lt;p&gt;현재 StackDay MVP에서는 하나의 &lt;code&gt;Habit&lt;/code&gt;에 대해 하루 한 번만 &lt;code&gt;Completion&lt;/code&gt;을 기록할 수 있다.&lt;/p&gt;
&lt;p&gt;그래서 처음에는 &lt;code&gt;(habitID, completedOn)&lt;/code&gt; 조합을 Completion의 identity처럼 사용해도 될 것 같았고, 실제로 그런 코드도 있었다.&lt;/p&gt;
&lt;p&gt;하지만 &lt;code&gt;Completion&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;Completion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Equatable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Identifiable&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="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UUID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;habitID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UUID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;completedOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;recordedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Date&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;h2 id="같은-날의-기록을-찾는-조건"&gt;같은 날의 기록을 찾는 조건&lt;/h2&gt;
&lt;p&gt;같은 &lt;code&gt;Habit&lt;/code&gt;의 같은 날 &lt;code&gt;Completion&lt;/code&gt;을 찾는 데에는 &lt;code&gt;habitID&lt;/code&gt;와 &lt;code&gt;completedOn&lt;/code&gt;이 필요하다. 현재 정책에서는 이 조건으로 중복 기록도 막을 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 이것은 현재 정책에서 필요한 조회 조건이다. 이후 시간 단위로 습관을 기록하거나, 하루에 여러 번 수행하는 &lt;code&gt;Habit&lt;/code&gt;이 생기면 같은 조합으로 여러 &lt;code&gt;Completion&lt;/code&gt;이 존재할 수 있다.&lt;/p&gt;</description></item><item><title>StackDay. Repository의 save를 insert와 update로 나누기</title><link>https://kelly-chui.github.io/posts/stackday-dev-log-repository-contracts/</link><pubDate>Fri, 14 Aug 2026 14:15:52 +0900</pubDate><guid>https://kelly-chui.github.io/posts/stackday-dev-log-repository-contracts/</guid><description>&lt;p&gt;유즈케이스를 구현하면서 &lt;code&gt;Habit&lt;/code&gt;과 &lt;code&gt;Completion&lt;/code&gt;을 저장할 Repository 계약을 좀 정리했다.&lt;/p&gt;
&lt;p&gt;처음에는 create와 update 둘 다 &lt;code&gt;save&lt;/code&gt; 하나로 저장하면 간단해 보였지만, 두 기능이 기대하는 실패 조건이 서로 다르다는 점에서 계약을 나눌 필요가 있었다.&lt;/p&gt;
&lt;h2 id="save는-어떤-동작인가"&gt;save는 어떤 동작인가&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;save&lt;/code&gt;를 upsert로 구현하면 호출하는 쪽은 편하다. ID가 없으면 삽입하고, 이미 있으면 갱신하면 된다.&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;protocol&lt;/span&gt; &lt;span class="nc"&gt;HabitRepository&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="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;_&lt;/span&gt; &lt;span class="n"&gt;habit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Habit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="kr"&gt;throws&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;p&gt;(물론 UUID라 현실적으로 겹칠 일은 없지만) &lt;code&gt;Habit&lt;/code&gt;을 생성하는 작업은 같은 ID가 이미 있으면 실패해야 하고, 보관처럼 기존 &lt;code&gt;Habit&lt;/code&gt;을 바꾸는 작업은 대상이 없으면 실패해야 한다.&lt;/p&gt;</description></item></channel></rss>