<?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>DIP on Kelly Dev</title><link>https://kelly-chui.github.io/tags/dip/</link><description>Recent content in DIP on Kelly Dev</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 10 Aug 2026 17:42:56 +0900</lastBuildDate><atom:link href="https://kelly-chui.github.io/tags/dip/index.xml" rel="self" type="application/rss+xml"/><item><title>dev-data-server-light. 0. Concept</title><link>https://kelly-chui.github.io/posts/devbox-light-server-00-concept/</link><pubDate>Wed, 24 Jun 2026 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/posts/devbox-light-server-00-concept/</guid><description>&lt;h2 id="시작하기"&gt;시작하기&lt;/h2&gt;
&lt;p&gt;iOS 프로젝트를 진행하다 보면 생각보다 자주 간단한 API 서버가 필요해진다. 회원가입 화면을 만들거나, 목록 조회 기능을 붙이거나, 이미지 업로드를 테스트할 때도 서버가 필요하다. 물론 실제 백엔드를 구축할 수도 있고, Supabase나 Firebase 같은 BaaS를 사용할 수도 있다. 하지만 작은 개인 프로젝트나 프로토타입 단계에서는 좋은 설계는 아니라고 생각한다.&lt;/p&gt;
&lt;p&gt;특히 처음부터 특정 서비스에 의존하기 시작하면, 정작 내가 만들고 싶은 앱의 기능보다 인프라 설정과 서비스 사용법을 익히는 데 더 많은 시간을 쓰게 된다. 앱 개발을 위한 도구가 필요했는데, 어느 순간 도구를 사용하기 위한 공부를 하고 있는 상황이 되는 것이다.&lt;/p&gt;</description></item><item><title>dev-data-server-light. 2. Database CRUD</title><link>https://kelly-chui.github.io/posts/devbox-light-server-02-db-crud/</link><pubDate>Tue, 30 Jun 2026 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/posts/devbox-light-server-02-db-crud/</guid><description>&lt;p&gt;시스템 모듈을 만든 이후에, 아마도 가장 많이 쓰게 될 DB 모듈을 만들었다.&lt;/p&gt;
&lt;img loading="lazy" src="https://kelly-chui.github.io/posts/devbox-light-server-02-db-crud/image-001-optimized-image.webp"&gt;&lt;p&gt;당시에는 구조도 시스템 모듈과 동일하다고 생각했다. Router가 DB 인터페이스에 의존하고, 이를 구현한 구현체를 주입받는 방식으로 DIP와 DI를 동시에 적용했다.&lt;/p&gt;
&lt;p&gt;이 과정 중에서&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;naming bias 해결하기&lt;/li&gt;
&lt;li&gt;id 생성 책임 위치&lt;/li&gt;
&lt;li&gt;기존 아키텍처의 문제점 -&amp;gt; 서비스 레이어 도입해서 해결하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;에 대한 고민을 했다. 아래는 고민과 해결 과정이다.&lt;/p&gt;
&lt;h2 id="crud부터-만들기"&gt;CRUD부터 만들기&lt;/h2&gt;
&lt;p&gt;Mock Server라도 최소한 CRUD는 제공해야 한다. 처음부터 구현체를 만들 필요는 없으므로, 라우터와 인터페이스까지만 만들도록 프롬프트를 작성했다.&lt;/p&gt;</description></item><item><title>dev-data-server-light. 3. Database Implementation</title><link>https://kelly-chui.github.io/posts/devbox-light-server-03-db-implementation/</link><pubDate>Thu, 02 Jul 2026 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/posts/devbox-light-server-03-db-implementation/</guid><description>&lt;p&gt;DB 모듈의 인터페이스와 서비스 레이어를 만들었으므로, 실제 구현체를 만들어야 한다. 우선 인 메모리(In-Memory)로 가볍게 구현체를 만들었다.&lt;/p&gt;
&lt;h2 id="인-메모리-데이터-저장소"&gt;인 메모리 데이터 저장소&lt;/h2&gt;
&lt;p&gt;인 메모리 방식을 선택한 이유는 첫째로 처음부터 SQL이나 JSON 파일 기반 저장소를 이용해서 구현체를 만드는 것 보다는, 가장 단순한 구현체를 만들어서 DB 기능을 검증하고 빠르게 다음 기능을 만들기 위해서이다. 외부 의존성도 없고, 설정도 필요 없고, 테스트도 쉽다.&lt;/p&gt;
&lt;h2 id="구현하기"&gt;구현하기&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;RecordStore&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-ts" data-lang="ts"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;RecordStore&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="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;StoredRecord&lt;/span&gt;&lt;span class="err"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;StoredRecord&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="na"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;: &lt;span class="kt"&gt;RecordData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;StoredRecord&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;: &lt;span class="kt"&gt;RecordData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;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;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;&amp;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;구현체는 이 계약을 그대로 만족하면 된다. 중요한 것은 구현체는 Express를 몰라야하고 순수하게 TypeScript 코드로 짜여야 한다. HTTP 요청이나 라우팅 같은 것은 Router가 책임져야 한다.&lt;/p&gt;</description></item><item><title>dev-data-server-light. 4. File Storage</title><link>https://kelly-chui.github.io/posts/devbox-light-server-04-file-storage/</link><pubDate>Thu, 02 Jul 2026 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/posts/devbox-light-server-04-file-storage/</guid><description>&lt;p&gt;DB 모듈을 마무리하고, 다음으로 구현한 것은 File Storage 모듈이다. DB 모듈과 크게 다르지 않을 것이라고 생각했다. 우선 CRUD 비슷한 메소드를 처리하고, 구조는 DB 모듈에서 충분히 다듬었기 때문이다. 하지만 실제로는 DB보다 인터페이스를 어떻게 정의할 것인지에 대한 고민이 더 많았다.&lt;/p&gt;
&lt;h2 id="인터페이스-만들기"&gt;인터페이스 만들기&lt;/h2&gt;
&lt;p&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-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Create the initial FileStorage contract in src/storage.
&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;Requirements:
&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;- Define a FileStorage interface.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- The interface is responsible only for storing and retrieving binary file contents.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- It should not manage file metadata, ids, ownership, permissions, or database records.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Use Buffer for file contents.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Include only the minimal operations required for file storage:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - save(path: string, content: Buffer): Promise&amp;lt;void&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - read(path: string): Promise&amp;lt;Buffer&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - delete(path: string): Promise&amp;lt;void&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - exists(path: string): Promise&amp;lt;boolean&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Add minimal domain errors if necessary.
&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;For this step, create only the contract and related types.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Do not implement any storage implementation yet.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;로컬 파일 시스템을 의식하고 있어서 의심 없이 &lt;code&gt;path&lt;/code&gt;라는 이름을 사용했는데, 이 때문에 인터페이스가 구현체를 닮아버리게 되었다. &lt;code&gt;path&lt;/code&gt;는 과연 인터페이스를 대표할 수 있는 네이밍인가?&lt;/p&gt;</description></item><item><title>devbox-light-server (5). Auth</title><link>https://kelly-chui.github.io/posts/devbox-light-server-05-auth/</link><pubDate>Sat, 08 Aug 2026 16:27:42 +0900</pubDate><guid>https://kelly-chui.github.io/posts/devbox-light-server-05-auth/</guid><description>&lt;h2 id="auth-설계하기"&gt;Auth 설계하기&lt;/h2&gt;
&lt;p&gt;개발용 목서버에서 실제 서비스 수준의 인증 시스템을 구현하지 않고도, 클라이언트에서 사용하는 로그인과 인증 흐름을 테스트할 수 있도록 Auth 기능을 추가했다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;로그인 요청을 보낸다.&lt;/li&gt;
&lt;li&gt;access token을 발급받는다.&lt;/li&gt;
&lt;li&gt;Authorization 헤더에 token을 실어 요청한다.&lt;/li&gt;
&lt;li&gt;현재 로그인된 유저를 확인한다.&lt;/li&gt;
&lt;li&gt;로그아웃으로 token을 무효화한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;JWT, 비밀번호, OAuth, Refresh Token, 보안 같은 기능은 의도적으로 제외했다. 프로덕션 인증 로직을 구현하려는 글이 아니라, 개발용 Mock 서버에서 클라이언트의 로그인, 인증, 로그아웃 흐름을 확인하는 것이 목적이기 때문이다.&lt;/p&gt;
&lt;h3 id="최소한의-auth-구조"&gt;최소한의 Auth 구조&lt;/h3&gt;
&lt;p&gt;첫 단계에서는 &lt;code&gt;DatabaseService&lt;/code&gt;를 그대로 사용했다. &lt;code&gt;users&lt;/code&gt; 컬렉션을 만들어서 그 레코드 ID를 유저 ID로 사용해 로그인할 수 있도록 했다.&lt;/p&gt;</description></item><item><title>devbox-light-server (6). Json 영속성</title><link>https://kelly-chui.github.io/posts/devbox-light-server-06-persistence/</link><pubDate>Mon, 10 Aug 2026 14:14:08 +0900</pubDate><guid>https://kelly-chui.github.io/posts/devbox-light-server-06-persistence/</guid><description>&lt;p&gt;MVP의 마지막 기능으로 서버를 재시작해도 데이터가 사라지지 않도록 영속성을 추가했다.&lt;/p&gt;
&lt;p&gt;이번 포스트에서는 devbox-light-server에 DB, Storage, Token Storage에서 영속성을 가진 저장 방식을 구현해서 in-memory 대신 사용할 수 있도록 만든다.&lt;/p&gt;
&lt;p&gt;프로토타입이었던 dev-data-server에서는 시작부터 SQL 의존성을 가지고 시작했지만, devbox-light-server는 아주 얇은 in-memory 구현만 가지고 있다.&lt;/p&gt;
&lt;p&gt;MVP 마지막에 영속성을 넣는 이유는 서버를 구현할 때, 특정 구현에 휘둘리지 않기 위해서다. dev-data-server에서 SQL을 빠르게 들여와서, 결국 프로젝트가 SQL 래퍼가 된 느낌이 있다.&lt;/p&gt;
&lt;p&gt;당연히 Service 레이어는 Repository의 인터페이스에만 의존하므로 어떤 방법을 쓰든 단순히 구현체만 갈아 끼우고, 의존성 생성, 연결 부분을 제외하고는 어떠한 코드에도 변화가 없어야 한다.&lt;/p&gt;</description></item><item><title>devbox-light-server (7). Dockerizing, MVP 마무리</title><link>https://kelly-chui.github.io/posts/devbox-light-server-07-dockerizing/</link><pubDate>Mon, 10 Aug 2026 17:42:56 +0900</pubDate><guid>https://kelly-chui.github.io/posts/devbox-light-server-07-dockerizing/</guid><description>&lt;h2 id="도커라이징"&gt;도커라이징&lt;/h2&gt;
&lt;p&gt;영속성까지 추가했으므로 이제 서버를 하나의 실행 단위로 묶을 차례다.&lt;/p&gt;
&lt;p&gt;지금까지는 로컬에서 Node.js를 설치하고, 의존성을 설치하고, TypeScript를 빌드한 다음 서버를 실행했다. 혼자 개발할 때는 큰 문제가 없지만, 이 서버를 다른 환경에서 실행하려면 매번 같은 준비 과정을 반복해야 한다.&lt;/p&gt;
&lt;p&gt;도커라이징은 이 과정을 이미지 안에 고정하는 작업이다. 이 프로젝트에서는 Express 서버를 빌드하고, 실행에 필요한 파일만 담은 뒤, &lt;code&gt;.data&lt;/code&gt; 디렉터리를 기준으로 데이터를 유지할 수 있도록 구성했다.&lt;/p&gt;
&lt;h3 id="dockerfile-작성하기"&gt;Dockerfile 작성하기&lt;/h3&gt;
&lt;p&gt;Dockerfile은 두 단계로 나눴다.&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-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:24-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;&lt;span class="err"&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;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app&lt;/span&gt;&lt;span class="err"&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;COPY&lt;/span&gt; package.json package-lock.json ./&lt;span class="err"&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;RUN&lt;/span&gt; npm ci&lt;span class="err"&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;COPY&lt;/span&gt; tsconfig.json tsconfig.build.json ./&lt;span class="err"&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;COPY&lt;/span&gt; src ./src&lt;span class="err"&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;RUN&lt;/span&gt; npm run build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;첫 번째 &lt;code&gt;build&lt;/code&gt; 단계에서는 개발 의존성을 포함해서 설치하고 TypeScript를 빌드한다. &lt;code&gt;npm run build&lt;/code&gt;를 실행하면 &lt;code&gt;dist&lt;/code&gt; 디렉터리가 만들어진다.&lt;/p&gt;</description></item><item><title>Software Engineering. DI와 DIP</title><link>https://kelly-chui.github.io/posts/se-dependency-injection/</link><pubDate>Thu, 27 Mar 2025 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/posts/se-dependency-injection/</guid><description>&lt;h2 id="의존성-주입dependency-injection"&gt;의존성 주입(Dependency Injection)&lt;/h2&gt;
&lt;p&gt;의존성 주입은 객체가 필요한 의존성을 내부에서 직접 생성하지 않고 외부에서 전달받는 방식이다. 별도의 DI 프레임워크나 주입 전용 객체가 반드시 필요한 것은 아니다. 생성자를 통해 객체를 전달하는 것만으로도 의존성 주입이 된다.&lt;/p&gt;
&lt;h2 id="의존의-의미"&gt;의존의 의미&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;A → B&lt;/code&gt;: &lt;code&gt;A&lt;/code&gt;가 &lt;code&gt;B&lt;/code&gt;에 의존한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;A&lt;/code&gt;가 동작하기 위해 &lt;code&gt;B&lt;/code&gt;의 타입이나 기능을 사용한다면 &lt;code&gt;A&lt;/code&gt;는 &lt;code&gt;B&lt;/code&gt;에 의존한다. &lt;code&gt;B&lt;/code&gt;의 공개 인터페이스가 바뀌면 &lt;code&gt;A&lt;/code&gt;도 영향을 받을 수 있다.&lt;/p&gt;
&lt;p&gt;다음 코드에서 &lt;code&gt;Greeter&lt;/code&gt;는 구체 타입인 &lt;code&gt;EnglishGreetingProvider&lt;/code&gt;를 직접 생성한다.&lt;/p&gt;
&lt;img alt="Screenshot 2024-09-29 at 4.21.47\u202fPM.png" loading="lazy" src="https://kelly-chui.github.io/posts/se-dependency-injection/image-001-optimized-image.webp"&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="kr"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EnglishGreetingProvider&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;greeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&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="s"&gt;&amp;#34;Hello, World!&amp;#34;&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="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="kr"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Greeter&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;private&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EnglishGreetingProvider&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="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;greet&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="bp"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;greeting&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;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;code&gt;Greeter&lt;/code&gt;를 직접 수정해야 한다.&lt;/p&gt;</description></item></channel></rss>