<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://clud.me/blog</id>
    <title>clud.me</title>
    <updated>2025-04-20T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://clud.me/blog"/>
    <subtitle>서동명의 개발 기록</subtitle>
    <icon>https://clud.me/img/favicon.png</icon>
    <rights>© 2026 Dongmyeong Seo</rights>
    <entry>
        <title type="html"><![CDATA[mikro-orm 알아보기]]></title>
        <id>https://clud.me/blog/mikro-orm</id>
        <link href="https://clud.me/blog/mikro-orm"/>
        <updated>2025-04-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[MikroORM은 Node.js 환경에서 데이터베이스 상호작용을 간소화하는 TypeScript ORM 라이브러리입니다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-mikroorm-개요">1. MikroORM 개요<a href="https://clud.me/blog/mikro-orm#1-mikroorm-%EA%B0%9C%EC%9A%94" class="hash-link" aria-label="1. MikroORM 개요에 대한 직접 링크" title="1. MikroORM 개요에 대한 직접 링크" translate="no">​</a></h2>
<p>MikroORM은 Node.js 환경에서 데이터베이스 상호작용을 간소화하는 TypeScript ORM 라이브러리입니다.</p>
<p>데이터 매퍼, Unit of Work, Identity Map 패턴을 기반으로 설계되었으며, MongoDB, MySQL, MariaDB, PostgreSQL, SQLite 등 다양한 데이터베이스를 지원합니다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="주요-기능">주요 기능<a href="https://clud.me/blog/mikro-orm#%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5" class="hash-link" aria-label="주요 기능에 대한 직접 링크" title="주요 기능에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">깔끔한 엔티티 정의</li>
<li class="">Identity Map과 엔티티 참조</li>
<li class="">엔티티 생성자 활용</li>
<li class="">관계 모델링과 컬렉션</li>
<li class="">Unit of Work</li>
<li class="">트랜잭션 지원</li>
<li class="">캐스케이딩 영속성과 삭제</li>
<li class="">필터와 쿼리 빌더</li>
<li class="">populate를 통한 중첩 구조 로딩</li>
<li class="">스키마와 엔티티 생성기</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-unit-of-work-패턴">2. Unit of Work 패턴<a href="https://clud.me/blog/mikro-orm#2-unit-of-work-%ED%8C%A8%ED%84%B4" class="hash-link" aria-label="2. Unit of Work 패턴에 대한 직접 링크" title="2. Unit of Work 패턴에 대한 직접 링크" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://app.studyraid.com/en/read/11519/361845/unit-of-work-pattern-in-mikroorm" target="_blank" rel="noopener noreferrer" class="">Unit of Work pattern in MikroORM - TypeScript Data Management with MikroORM and ORM Patterns</a></p></div></div>
<p>Unit of Work 패턴은 MikroORM의 핵심 설계 패턴으로서, 엔티티의 변경사항(삽입, 수정, 삭제)을 관리하고 단일 트랜잭션에서 영속화를 조정합니다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="핵심-개념">핵심 개념<a href="https://clud.me/blog/mikro-orm#%ED%95%B5%EC%8B%AC-%EA%B0%9C%EB%85%90" class="hash-link" aria-label="핵심 개념에 대한 직접 링크" title="핵심 개념에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Unit of Work는 다음 세 가지 주요 엔티티 상태를 추적
<ul>
<li class="">새로운 엔티티 (삽입 예정)</li>
<li class="">수정된 엔티티 (업데이트 예정)</li>
<li class="">제거된 엔티티 (삭제 예정)</li>
</ul>
</li>
</ul>
<p>이러한 변경사항은 비즈니스 트랜잭션 중에 수집되며, Unit of Work 커밋 시 원자적으로 영속화됩니다. 이는 데이터 일관성을 보장하고 데이터베이스 작업을 최소화합니다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="변경-감지-메커니즘">변경 감지 메커니즘<a href="https://clud.me/blog/mikro-orm#%EB%B3%80%EA%B2%BD-%EA%B0%90%EC%A7%80-%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98" class="hash-link" aria-label="변경 감지 메커니즘에 대한 직접 링크" title="변경 감지 메커니즘에 대한 직접 링크" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://mikro-orm.github.io/docs/v3/unit-of-work/" target="_blank" rel="noopener noreferrer" class="">Unit of Work and Transactions</a></p></div></div>
<p>MikroORM은 정교한 변경 감지 메커니즘을 사용합니다. 엔티티를 데이터베이스에서 로드할 때 해당 시점의 스냅샷을 저장하고, flush() 호출 시 현재 상태와 비교하여 변경사항을 파악합니다.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 변경 감지 예시</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> article </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Article</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">article</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">content </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'업데이트된 내용'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flush</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 변경된 필드만 업데이트</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-영속화persist-이해하기">3. 영속화(Persist) 이해하기<a href="https://clud.me/blog/mikro-orm#3-%EC%98%81%EC%86%8D%ED%99%94persist-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0" class="hash-link" aria-label="3. 영속화(Persist) 이해하기에 대한 직접 링크" title="3. 영속화(Persist) 이해하기에 대한 직접 링크" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://stackoverflow.com/questions/66386900/are-entities-created-with-em-create-managed-and-persisted" target="_blank" rel="noopener noreferrer" class="">Are entities created with em.create managed and persisted?</a></p></div></div>
<p>영속화(persist)는 엔티티를 EntityManager에 의해 관리되도록 등록하는 과정입니다. persist 호출은 즉시 데이터베이스에 쓰기를 수행하지 않으며, 대신 엔티티를 추적하고 후속 flush 호출 시 데이터베이스에 저장하도록 표시합니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'John Doe'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">persist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 관리 상태로 표시됨</span><br></div></code></pre></div></div>
<p>persist 메서드는 엔티티가 관리 상태로 들어가는 것을 의미하며, 이 상태에서 MikroORM은 엔티티의 변경사항을 추적할 수 있습니다</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-flush-작업-이해하기">4. Flush 작업 이해하기<a href="https://clud.me/blog/mikro-orm#4-flush-%EC%9E%91%EC%97%85-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0" class="hash-link" aria-label="4. Flush 작업 이해하기에 대한 직접 링크" title="4. Flush 작업 이해하기에 대한 직접 링크" translate="no">​</a></h2>
<p>flush는 관리되는 모든 엔티티의 변경사항을 계산하고 이를 데이터베이스에 적용하는 과정입니다. em.flush()를 호출하면 모든 계산된 변경사항이 데이터베이스 트랜잭션 내에서 쿼리됩니다(해당 드라이버가 지원하는 경우)</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">User</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">email </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'foo@bar.com'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> car </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Car</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cars</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">car</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 양방향 캐스케이딩 덕분에 user 엔티티만 영속화하면 됨</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// flush는 트랜잭션을 생성하고, 새 car를 삽입하고, user의 이메일을 업데이트함</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flush</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>flush는 변경된 엔티티와 속성만을 데이터베이스에 쿼리하여 성능을 최적화합니다. 변경사항이 없으면 트랜잭션도 시작되지 않습니다</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-persist-와-flush-사용-시점">5. Persist 와 Flush 사용 시점<a href="https://clud.me/blog/mikro-orm#5-persist-%EC%99%80-flush-%EC%82%AC%EC%9A%A9-%EC%8B%9C%EC%A0%90" class="hash-link" aria-label="5. Persist 와 Flush 사용 시점에 대한 직접 링크" title="5. Persist 와 Flush 사용 시점에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="persist-사용-시점">Persist 사용 시점<a href="https://clud.me/blog/mikro-orm#persist-%EC%82%AC%EC%9A%A9-%EC%8B%9C%EC%A0%90" class="hash-link" aria-label="Persist 사용 시점에 대한 직접 링크" title="Persist 사용 시점에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>생성자로 새 엔티티를 생성했을 때</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> entity </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Entity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Object</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assign</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">entity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">persiste</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">entity</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 수동 호출 필요</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>엔티티를 EntityManager에 의해 관리되도록 표시하고 싶을 때</p>
<ul>
<li class="">persist()는 새로운 엔티티를 Identity Map에 등록하기 위한 메서드입니다.</li>
<li class="">DB에서 조회된 기존 엔티티는 이미 Managed 상태이므로 persist() 호출이 필요 없습니다.</li>
</ul>
</li>
<li class="">
<p>여러 엔티티를 수정하고 이후에 한 번에 플러시하고 싶을 때</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="flush-사용-시점">Flush 사용 시점<a href="https://clud.me/blog/mikro-orm#flush-%EC%82%AC%EC%9A%A9-%EC%8B%9C%EC%A0%90" class="hash-link" aria-label="Flush 사용 시점에 대한 직접 링크" title="Flush 사용 시점에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">모든 변경사항을 데이터베이스에 적용하고 싶을 때</li>
<li class="">트랜잭션 경계를 제어하고 싶을 때</li>
<li class="">변경사항들이 준비되어 단일 트랜잭션으로 실행하고 싶을 때</li>
</ul>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 여러 엔티티 처리를 위한 패턴</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> users </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1000</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c">user</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">i</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">@example.com</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  users</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">push</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">persist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 모든 1000명의 사용자가 효율적인 배치로 삽입됨</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flush</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>이 패턴은 트랜잭션 경계를 제어하는 데 유용하며, em.persist()를 호출하여 변경사항을 표시하고 준비가 되면 flush()를 호출하여 트랜잭션 내에서 실행할 수 있습니다</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-entitymanagercreate-사용-시점">6. EntityManager.create 사용 시점<a href="https://clud.me/blog/mikro-orm#6-entitymanagercreate-%EC%82%AC%EC%9A%A9-%EC%8B%9C%EC%A0%90" class="hash-link" aria-label="6. EntityManager.create 사용 시점에 대한 직접 링크" title="6. EntityManager.create 사용 시점에 대한 직접 링크" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://mikro-orm.io/api/knex/class/EntityManager#create" target="_blank" rel="noopener noreferrer" class="">EntityManager | API | MikroORM</a></p><p><a href="https://mikro-orm.io/docs/entity-constructors" target="_blank" rel="noopener noreferrer" class="">Using Entity Constructors | MikroORM</a></p><ul>
<li class="">v5.5부터 persistOnCreate 옵션의 기본값이 true로 변경되었습니다.</li>
<li class="">em.create()로 생성된 엔티티는 별도의 em.persist() 호출 없이 자동으로 관리 상태가 되고 persist 예약(INSERT 예정)됩니다.</li>
<li class="">원치 않는 경우, 옵션으로 { persist: false }를 설정하거나 전역 설정으로 persistOnCreate: false를 명시해야 합니다</li>
</ul></div></div>
<blockquote>
<p>Creates new instance of given entity and populates it with given data. The entity constructor will be used unless you provide { managed: true } in the options parameter. The constructor will be given parameters based on the defined constructor of the entity. If the constructor parameter matches a property name, its value will be extracted from data. If no matching property exists, the whole data parameter will be passed. This means we can also define constructor(data: Partial&lt;T&gt;) and em.create() will pass the data into it (unless we have a property named data too).</p>
<p>The parameters are strictly checked, you need to provide all required properties. You can use OptionalProps symbol to omit some properties from this check without making them optional. Alternatively, use partial: true in the options to disable the strict checks for required properties. This option has no effect on runtime.</p>
<p>The newly created entity will be automatically marked for persistence via em.persist unless you disable this behavior, either locally via persist: false option, or globally via persistOnCreate ORM config option.</p>
</blockquote>
<p>EntityManager.create 메서드는 새 엔티티 인스턴스를 생성하는 유틸리티 메서드입니다. 이는 EntityFactory의 단축형으로, ‘new’ 연산자를 통해 수동으로 클래스를 인스턴스화하는 것과 유사합니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 기본 인스턴스화</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'John Doe'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// em.create를 통한 인스턴스화</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">User</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'John Doe'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'john@example.com'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flush</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>em.create의 주요 이점은 엔티티 생성자와 파라미터를 자동으로 감지하고 존중한다는 것입니다. 엔티티 속성 이름과 동일한 이름의 파라미터를 사용해야 합니다</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-asynclocalstorage와-mikroorm에서의-동작">7. AsyncLocalStorage와 MikroORM에서의 동작<a href="https://clud.me/blog/mikro-orm#7-asynclocalstorage%EC%99%80-mikroorm%EC%97%90%EC%84%9C%EC%9D%98-%EB%8F%99%EC%9E%91" class="hash-link" aria-label="7. AsyncLocalStorage와 MikroORM에서의 동작에 대한 직접 링크" title="7. AsyncLocalStorage와 MikroORM에서의 동작에 대한 직접 링크" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://nodejs.org/api/async_context.html" target="_blank" rel="noopener noreferrer" class="">Asynchronous context tracking | Node.js v23.11.0 Documentation</a></p><p><a href="https://mikro-orm.io/docs/identity-map#how-does-requestcontext-helper-work" target="_blank" rel="noopener noreferrer" class="">Identity Map and Request Context | MikroORM</a></p><p><a href="https://remocon33.tistory.com/707" target="_blank" rel="noopener noreferrer" class="">Node.js - async_hooks 소개</a></p></div></div>
<p>AsyncLocalStorage는 Node.js의 코어 기능으로, 비동기 호출 전반에 걸쳐 컨텍스트를 추적합니다. 웹 요청이나 기타 비동기 실행 기간 동안 데이터를 저장할 수 있게 해주며, 다른 언어의 스레드-로컬 스토리지와 유사합니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> AsyncLocalStorage </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'node:async_hooks'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> asyncLocalStorage </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">AsyncLocalStorage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">logWithId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">msg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> asyncLocalStorage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getStore</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token builtin">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">id </span><span class="token template-string interpolation operator" style="color:#393A34">!==</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation keyword" style="color:#00009f">undefined</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation operator" style="color:#393A34">?</span><span class="token template-string interpolation"> id </span><span class="token template-string interpolation operator" style="color:#393A34">:</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation string" style="color:#e3116c">'-'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">:</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> msg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 요청 처리 중 ID 유지</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">asyncLocalStorage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">logWithId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'시작'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 비동기 작업...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">setImmediate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">logWithId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'종료'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 여전히 같은 ID에 접근 가능</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>MikroORM에서 AsyncLocalStorage는 RequestContext 헬퍼를 통해 사용됩니다. 이 헬퍼는 요청 컨텍스트를 격리하여 각 요청마다 고유한 EntityManager 인스턴스(fork)를 사용할 수 있게 합니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 미들웨어에서 요청 컨텍스트 생성</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">req</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> next</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  RequestContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">orm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> next</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'/'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">req</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 비동기 컨텍스트에서 자동으로 fork 사용</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> authors </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> orm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Book</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  res</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">json</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authors</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>내부적으로 EntityManager의 모든 메서드는 먼저 em.getContext()를 호출하여 현재 컨텍스트의 EntityManager를 사용합니다. 이로써 요청별로 독립된 Identity Map을 유지할 수 있습니다</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="8-mongodb-트랜잭션-사용-시-주의사항">8. MongoDB 트랜잭션 사용 시 주의사항<a href="https://clud.me/blog/mikro-orm#8-mongodb-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EC%82%AC%EC%9A%A9-%EC%8B%9C-%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD" class="hash-link" aria-label="8. MongoDB 트랜잭션 사용 시 주의사항에 대한 직접 링크" title="8. MongoDB 트랜잭션 사용 시 주의사항에 대한 직접 링크" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://rastalion.dev/mongodb-transaction-management/" target="_blank" rel="noopener noreferrer" class="">MongoDB Transaction Management - RastaLion.dev</a></p><p><a href="https://www.mongodb.com/blog/post/performance-best-practices-transactions-and-read-write-concerns" target="_blank" rel="noopener noreferrer" class="">Performance Best Practices: Transactions and Read / Write Concerns | MongoDB Blog</a></p><p><a href="https://velog.io/@sonar0/MongoDB-Transaction" target="_blank" rel="noopener noreferrer" class="">MongoDB Transaction</a></p></div></div>
<p>MongoDB와 함께 MikroORM의 트랜잭션 기능을 사용할 때는 여러 제약사항을 고려해야 합니다</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="주요-제약사항">주요 제약사항<a href="https://clud.me/blog/mikro-orm#%EC%A3%BC%EC%9A%94-%EC%A0%9C%EC%95%BD%EC%82%AC%ED%95%AD" class="hash-link" aria-label="주요 제약사항에 대한 직접 링크" title="주요 제약사항에 대한 직접 링크" translate="no">​</a></h3>
<ol>
<li class="">
<p>레플리카 셋 필요: MongoDB에서 트랜잭션을 사용하려면 레플리카 셋 구성이 필요합니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> orm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> MikroORM</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  entities</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Author</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Book</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">...</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  clientUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mongodb://localhost:27017,localhost:27018,localhost:27019/my-db-name?replicaSet=rs0'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  implicitTransactions</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 기본값은 false</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>시간 제한: MongoDB의 기본 트랜잭션 제한은 60초이며, 이를 초과하면 자동으로 중단됩니다</p>
</li>
<li class="">
<p>문서 수정 제한: 모범 사례로, 트랜잭션 내에서 1,000개 이상의 문서를 수정하지 않는 것이 좋습니다</p>
</li>
<li class="">
<p>캐시 압력: 장시간 실행되는 트랜잭션은 WiredTiger 스토리지 엔진 캐시에 높은 압력을 줄 수 있습니다</p>
</li>
<li class="">
<p>다중 샤드 트랜잭션: 여러 샤드에 영향을 미치는 트랜잭션은 네트워크를 통해 작업이 조정되어야 하므로 더 많은 성능 비용이 발생합니다</p>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="권장사항">권장사항<a href="https://clud.me/blog/mikro-orm#%EA%B6%8C%EC%9E%A5%EC%82%AC%ED%95%AD" class="hash-link" aria-label="권장사항에 대한 직접 링크" title="권장사항에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">트랜잭션을 더 작은 부분으로 나누어 시간 제한 내에 실행되도록 합니다.</li>
<li class="">적절한 인덱싱을 통해 쿼리 성능을 최적화합니다.</li>
<li class="">트랜잭션 사용을 최소화하기 위해 데이터 스키마 설계를 고려합니다.</li>
<li class="">실패한 트랜잭션을 재시도하는 로직을 구현합니다.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="9-identity-map과-request-context-자세한-소개">9. Identity Map과 Request Context 자세한 소개<a href="https://clud.me/blog/mikro-orm#9-identity-map%EA%B3%BC-request-context-%EC%9E%90%EC%84%B8%ED%95%9C-%EC%86%8C%EA%B0%9C" class="hash-link" aria-label="9. Identity Map과 Request Context 자세한 소개에 대한 직접 링크" title="9. Identity Map과 Request Context 자세한 소개에 대한 직접 링크" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://mikro-orm.io/blog/introducing-mikroorm-typescript-data-mapper-orm-with-identity-map" target="_blank" rel="noopener noreferrer" class="">Introducing MikroORM, TypeScript data-mapper ORM with Identity Map | MikroORM</a></p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="identity-map">Identity Map<a href="https://clud.me/blog/mikro-orm#identity-map" class="hash-link" aria-label="Identity Map에 대한 직접 링크" title="Identity Map에 대한 직접 링크" translate="no">​</a></h3>
<p>Identity Map은 MikroORM이 객체를 추적하는 패턴입니다. 데이터베이스에서 엔티티를 가져올 때마다, MikroORM은 해당 엔티티의 참조를 UnitOfWork 내에 유지합니다</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="주요-이점">주요 이점<a href="https://clud.me/blog/mikro-orm#%EC%A3%BC%EC%9A%94-%EC%9D%B4%EC%A0%90" class="hash-link" aria-label="주요 이점에 대한 직접 링크" title="주요 이점에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>엔티티 유일성: 동일한 ID를 가진 엔티티를 여러 번 요청해도 항상 같은 인스턴스를 반환합니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> jon1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> authorRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> jon2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> authorRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">jon1 </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> jon2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// true</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>데이터베이스 호출 최적화: 이미 로드된 엔티티를 다시 요청할 경우, MikroORM은 Identity Map을 먼저 확인하고 데이터베이스 접근을 건너뜁니다</p>
</li>
<li class="">
<p>변경 감지: em.flush() 호출 시, MikroORM은 Identity Map을 통해 현재 관리되는 모든 엔티티를 확인하고 변경사항을 계산합니다</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="identity-map-병합-메커니즘">Identity Map 병합 메커니즘<a href="https://clud.me/blog/mikro-orm#identity-map-%EB%B3%91%ED%95%A9-%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98" class="hash-link" aria-label="Identity Map 병합 메커니즘에 대한 직접 링크" title="Identity Map 병합 메커니즘에 대한 직접 링크" translate="no">​</a></h3>
<ol>
<li class="">DB에서 조회한 데이터와 Identity Map의 엔티티를 비교</li>
<li class="">동일 PK가 존재할 경우:
<ol>
<li class="">Identity Map의 변경 사항 우선 적용</li>
<li class="">DB 데이터는 무시 (단, refresh: true 옵션 사용 시 덮어씀)
<ol>
<li class="">동일 PK의 엔티티가 이미 Identity Map에 존재할 경우, 해당 엔티티는 DB 조회 데이터를 통해 덮어씌워지지 않음</li>
<li class="">이미 메모리 내에 존재하는 엔티티를 최신 상태로 간주하여, DB 조회로 인해 변경 사항이 자동으로 사라지지 않도록 보호함</li>
<li class="">refresh: true 옵션을 통해 DB에서 가져온 데이터를 강제로 반영할 수 있음</li>
</ol>
</li>
</ol>
</li>
<li class="">병합 과정에서 flush가 발생하지 않음</li>
</ol>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 1. 엔티티 수정 (flush 미실행)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> author </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Author</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">author</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Dirty Data'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 2. 비-PK 조회 실행</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> authors </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Author</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'test@test.com'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 3. 결과 분석</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUnitOfWork</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getScheduledCollections</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ▶️ 스케줄링된 flush 작업 존재 확인 (flush가 아직 안 된 상태)</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="request-context">Request Context<a href="https://clud.me/blog/mikro-orm#request-context" class="hash-link" aria-label="Request Context에 대한 직접 링크" title="Request Context에 대한 직접 링크" translate="no">​</a></h3>
<p>RequestContext는 웹 애플리케이션에서 각 요청마다 독립된 Identity Map을 유지하기 위한 헬퍼입니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 미들웨어로 요청 컨텍스트 설정</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addHook</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'onRequest'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> reply</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> done</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  RequestContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">orm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> done</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 각 요청은 자체 Identity Map을 가짐</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'/article'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> request </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> limit</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> offset </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">query </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> limit</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> offset</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">items</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> total</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> db</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">article</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findAndCount</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    limit</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> offset</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> items</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> total </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>RequestContext는 Node.js의 AsyncLocalStorage API를 사용하여 비동기 호출 전반에 걸쳐 컨텍스트를 유지합니다</p>
<p>HTTP 요청 외에도, 큐 핸들러나 스케줄된 작업과 같은 상황에서는 @CreateRequestContext() 데코레이터를 사용할 수 있습니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">Injectable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">MyService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> orm</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> MikroORM</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">CreateRequestContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doSomething</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 별도의 컨텍스트에서 실행됨</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="10-중첩된-컨텍스트-처리">10. 중첩된 컨텍스트 처리<a href="https://clud.me/blog/mikro-orm#10-%EC%A4%91%EC%B2%A9%EB%90%9C-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC" class="hash-link" aria-label="10. 중첩된 컨텍스트 처리에 대한 직접 링크" title="10. 중첩된 컨텍스트 처리에 대한 직접 링크" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://mikro-orm.io/docs/usage-with-nestjs" target="_blank" rel="noopener noreferrer" class="">Using MikroORM with NestJS framework | MikroORM</a></p><p><a href="https://github.com/mikro-orm/mikro-orm/issues/3338" target="_blank" rel="noopener noreferrer" class="">https://github.com/mikro-orm/mikro-orm/issues/3338</a></p></div></div>
<p>MikroORM에서 컨텍스트가 중첩될 때 발생할 수 있는 몇 가지 중요한 고려사항이 있습니다</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="주요-제약사항-1">주요 제약사항<a href="https://clud.me/blog/mikro-orm#%EC%A3%BC%EC%9A%94-%EC%A0%9C%EC%95%BD%EC%82%AC%ED%95%AD-1" class="hash-link" aria-label="주요 제약사항에 대한 직접 링크" title="주요 제약사항에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>데코레이터 중첩 금지: @CreateRequestContext() 데코레이터는 최상위 메서드에만 사용해야 하며, 중첩해서 사용하면 안 됩니다</p>
</li>
<li class="">
<p>무한 재귀 위험: 기존 컨텍스트 내에서 fork를 생성하면 Maximum call stack size exceeded 오류가 발생할 수 있습니다. 이는 fork 함수가 내부적으로 getContext를 호출하기 때문입니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 이런 패턴은 문제를 일으킬 수 있음</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">context</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> storage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getStore</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 컨텍스트 내에서 fork를 생성하면 무한 루프가 발생할 수 있음</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>복잡한 애플리케이션: 복잡한 애플리케이션에서 여러 컨텍스트나 MikroORM 인스턴스가 필요한 경우, 기본 RequestContext 설정으로 문제가 발생할 수 있습니다</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="해결-방법">해결 방법<a href="https://clud.me/blog/mikro-orm#%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95" class="hash-link" aria-label="해결 방법에 대한 직접 링크" title="해결 방법에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>컨텍스트 외부에서 fork 생성: 컨텍스트 외부에서 fork를 생성하고 저장하는 방식을 사용합니다</p>
</li>
<li class="">
<p>커스텀 AsyncLocalStorage 인스턴스: 자체 AsyncLocalStorage 인스턴스를 생성하고 컨텍스트 옵션을 통해 MikroORM에 제공합니다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> storage </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">AsyncLocalStorage</span><span class="token class-name operator" style="color:#393A34">&lt;</span><span class="token class-name">EntityManager</span><span class="token class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> orm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> MikroORM</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">context</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> storage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getStore</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">req</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> next</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  storage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">orm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fork</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> next</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>작업 분할: 서로 다른 컨텍스트를 필요로 하는 작업을 별도의 메서드나 서비스로 분리합니다</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="예시-케이스">예시 케이스<a href="https://clud.me/blog/mikro-orm#%EC%98%88%EC%8B%9C-%EC%BC%80%EC%9D%B4%EC%8A%A4" class="hash-link" aria-label="예시 케이스에 대한 직접 링크" title="예시 케이스에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="동일-엔티티를-트랜잭션에서-처리한-경우">동일 엔티티를 트랜잭션에서 처리한 경우<a href="https://clud.me/blog/mikro-orm#%EB%8F%99%EC%9D%BC-%EC%97%94%ED%8B%B0%ED%8B%B0%EB%A5%BC-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%97%90%EC%84%9C-%EC%B2%98%EB%A6%AC%ED%95%9C-%EA%B2%BD%EC%9A%B0" class="hash-link" aria-label="동일 엔티티를 트랜잭션에서 처리한 경우에 대한 직접 링크" title="동일 엔티티를 트랜잭션에서 처리한 경우에 대한 직접 링크" translate="no">​</a></h3>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 1. 초기 조회 및 변경</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> author1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> authorRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// DB에서 '원본' 값 로드</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">author1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Wow'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 변경 사항 기록 (아직 DB 반영 X)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 2. 트랜잭션 블록</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">transactional</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> author </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> authorRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Identity Map에서 동일 인스턴스 획득</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  author</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Hello'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 즉시 author1에도 반영됨</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 트랜잭션 종료 시 암시적 flush 발생 → DB에 'Hello' 저장</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 3. 출력 시점</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">author1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 'Hello' 출력</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 4. 추가 변경 및 명시적 flush</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">author1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Good'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flush</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 최종적으로 'Good'이 DB에 저장</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="identity-map-을-fork-한-경우">Identity Map 을 fork 한 경우<a href="https://clud.me/blog/mikro-orm#identity-map-%EC%9D%84-fork-%ED%95%9C-%EA%B2%BD%EC%9A%B0" class="hash-link" aria-label="Identity Map 을 fork 한 경우에 대한 직접 링크" title="Identity Map 을 fork 한 경우에 대한 직접 링크" translate="no">​</a></h3>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 1. 초기 엔티티 로드</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> author1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> authorRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 원본 Identity Map에 저장</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">author1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Wow'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 변경 사항 추적 시작</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 2. fork()로 생성된 새 EntityManager에서 작업</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fork</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">transactional</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">forkedEm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> author </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> forkedEm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Author</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 분리된 Identity Map에서 새 인스턴스 로드</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  author</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Hello'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// fork된 인스턴스만 수정</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 트랜잭션 종료 시 fork된 인스턴스의 변경사항('Hello') DB 반영</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 3. 출력 시점</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">author1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 'Wow' 출력 → 원본 인스턴스 영향 없음</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 4. 원본 인스턴스 추가 수정</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">author1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Good'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flush</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 원본 인스턴스의 'Good'이 최종 저장</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="auto-flush-false-인-경우">Auto Flush (false 인 경우)<a href="https://clud.me/blog/mikro-orm#auto-flush-false-%EC%9D%B8-%EA%B2%BD%EC%9A%B0" class="hash-link" aria-label="Auto Flush (false 인 경우)에 대한 직접 링크" title="Auto Flush (false 인 경우)에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">기본 동작
<ul>
<li class="">PK 조회: Identity Map 의 엔티티 즉시 반환</li>
<li class="">비-PK 조회: DB 쿼리 실행 → 결과를 Identity Map 과 병합</li>
</ul>
</li>
</ul>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> author </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Author</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// PK 조회 → Identity Map 사용</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">author</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Changed'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 변경 사항 기록 (아직 flush 안 됨)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 비-PK 조건으로 조회</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> authors </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Author</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Changed'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 1. DB 쿼리 실행 (변경 전 데이터 조회)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 2. Identity Map과 병합 → author 인스턴스의 변경 사항('Changed')이 우선 적용</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 3. flush 발생 ❌ (단순 병합만 수행)</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="auto-flush-true-인-경우">Auto Flush (true 인 경우)<a href="https://clud.me/blog/mikro-orm#auto-flush-true-%EC%9D%B8-%EA%B2%BD%EC%9A%B0" class="hash-link" aria-label="Auto Flush (true 인 경우)에 대한 직접 링크" title="Auto Flush (true 인 경우)에 대한 직접 링크" translate="no">​</a></h3>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> orm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> MikroORM</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  autoFlush</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 모든 쿼리 전 자동 flush</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 변경 사항이 있을 경우 모든 조회 전 자동 flush</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">author</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'New Value'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Author</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'New Value'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 자동 flush 발생 → 변경 사항 DB 반영</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="flushmode-auto">FlushMode: Auto<a href="https://clud.me/blog/mikro-orm#flushmode-auto" class="hash-link" aria-label="FlushMode: Auto에 대한 직접 링크" title="FlushMode: Auto에 대한 직접 링크" translate="no">​</a></h3>
<p>Mikro-ORM v5에서 FlushMode.AUTO가 기본값으로 설정되어 있어, 컬렉션 조회 시 자동 flush가 발생하는 현상입니다. 이는 ORM이 쿼리 결과의 정합성을 보장하기 위해 설계된 동작입니다</p>
<ul>
<li class="">
<p>FlushMode.AUTO 기본 동작</p>
<ul>
<li class="">
<p>v5에서는 FlushMode.AUTO가 기본값으로, 쿼리와 변경 사항이 겹칠 경우 자동 flush를 트리거합니다.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 새로운 엔티티 생성 및 연결</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> parent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Parent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">parent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">children</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Child</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 변경 사항 기록 (flush 전)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 컬렉션 조회 시 자동 flush 발생</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> children </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Child</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> parent </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 자동 flush!</span><br></div></code></pre></div></div>
</li>
</ul>
</li>
<li class="">
<p>쿼리와 변경 사항의 겹침(Overlap) 검출</p>
<ul>
<li class="">관계 필드 조회: parent.children 컬렉션을 조회하면 해당 관계와 연결된 모든 변경 사항이 검출됩니다</li>
<li class="">Identity Map 동기화: 쿼리 실행 전 변경 사항이 DB에 반영되지 않으면 데이터 불일치 발생 가능성이 있으므로 ORM이 자동으로 flush를 수행합니다</li>
</ul>
</li>
<li class="">
<p>상세 동작 메커니즘</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 1. 신규 엔티티 생성</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> child </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Child</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">parent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">children</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">child</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Unit of Work에 변경 사항 등록</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 2. 컬렉션 조회 시 Mikro-ORM 내부 로직</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Child</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> parent</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> parent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/*</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">- 변경 사항 확인: parent.children에 새로운 child 존재</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">- Flush 필요성 판단: 쿼리 조건(parent.id)과 변경 사항(child.parent_id)이 겹침</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">- 자동 flush 실행: child INSERT 쿼리 발생</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">*/</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>해결 방법</p>
<ul>
<li class="">
<p>Flush Mode 변경</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// COMMIT 모드로 설정 (트랜잭션 커밋 시에만 flush)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setFlushMode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">FlushMode</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">COMMIT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>명시적 트랜잭션 사용</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">await em.transactional(async () =&gt; {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  parent.children.add(new Child());</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  // 트랜잭션 내 조회 시 flush 발생하지 않음</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  const children = await em.find(Child, { parent });</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">});</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>EntityManager 분리</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> forkedEm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fork</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 새로운 컨텍스트 생성</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">forkedEm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">persist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">parent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">children</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Child</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// fork된 인스턴스에서 조회 (기존 변경 사항과 격리)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> children </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> forkedEm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Child</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> parent </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>Cascade 설정 조정</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">OneToMany</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> Child</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> child </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> child</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">parent</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  cascade</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Cascade.PERSIST 비활성화</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">children </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token class-name operator" style="color:#393A34">&lt;</span><span class="token class-name">Child</span><span class="token class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
</ul>
</li>
<li class="">
<p>예방 패턴</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 1. Flush Mode 명시적 설정</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> orm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> MikroORM</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  flushMode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> FlushMode</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">COMMIT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 기본값 변경</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 2. 트랜잭션 범위 제한</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">transactional</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 작업 수행</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> flushMode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> FlushMode</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">COMMIT</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 3. 배치 작업 시 수동 제어</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">parent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">children</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Child</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flush</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 명시적 실행 후 조회</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> children </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> em</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Child</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> parent </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="emcreate-옵션">em.create 옵션<a href="https://clud.me/blog/mikro-orm#emcreate-%EC%98%B5%EC%85%98" class="hash-link" aria-label="em.create 옵션에 대한 직접 링크" title="em.create 옵션에 대한 직접 링크" translate="no">​</a></h3>






























<table><thead><tr><th><strong>구분</strong></th><th><strong>managed: true</strong></th><th><strong>persist: true</strong></th></tr></thead><tbody><tr><td>목적</td><td>Identity Map 등록 (변경 추적)</td><td>DB 저장 예약 (INSERT)</td></tr><tr><td>flush 영향</td><td>변경 감지 O</td><td>변경 감지 +</td></tr><tr><td>사용 시나리오</td><td>기존 엔티티 수정 추적</td><td>신규 엔티티 삽입</td></tr><tr><td>주의</td><td></td><td>mikro-orm v5.5 이상부터는 global persistOnCreate 옵션을 따라가기 때문에 사용할 일이 거의 없음</td></tr></tbody></table>
<ul>
<li class="">managed: true ➔ 생성한 엔티티는 즉시 관리 상태가 되어 변경사항 추적이 가능하지만, 데이터베이스에 INSERT 예약은 하지 않으므로 신규 엔티티의 경우 별도로 em.persist() 호출이 필요합니다</li>
<li class="">persist: true ➔ 신규 엔티티 INSERT 예약
<ul>
<li class="">persist: true 는 자동으로 managed 상태로 전환</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="결론">결론<a href="https://clud.me/blog/mikro-orm#%EA%B2%B0%EB%A1%A0" class="hash-link" aria-label="결론에 대한 직접 링크" title="결론에 대한 직접 링크" translate="no">​</a></h2>
<p>MikroORM은 Node.js와 TypeScript를 위한 강력한 ORM으로, 특히 Unit of Work와 Identity Map 패턴을 통해 엔티티 상태 관리와 데이터베이스 상호작용을 효율적으로 처리합니다.</p>
<p>MongoDB와의 통합에서도 트랜잭션 지원을 통해 데이터 일관성을 유지할 수 있습니다.</p>
<p>persist와 flush 메커니즘을 이해하고 적절히 활용하면 애플리케이션 성능을 최적화하고 복잡한 비즈니스 로직도 효과적으로 구현할 수 있습니다.</p>
<p>RequestContext와 AsyncLocalStorage를 통한 컨텍스트 관리는 웹 애플리케이션에서 요청별로 독립된 엔티티 관리를 가능하게 하며, 이를 통해 안정적이고 확장 가능한 시스템을 구축할 수 있습니다.</p>
<p>MongoDB 트랜잭션의 제약사항을 이해하고 적절히 대응함으로써, MikroORM과 MongoDB의 조합이 제공하는 모든 장점을 최대한 활용할 수 있을 것입니다.</p>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="Node.js" term="Node.js"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[도메인 주도 설계 철저 입문]]></title>
        <id>https://clud.me/blog/ddd-introduction</id>
        <link href="https://clud.me/blog/ddd-introduction"/>
        <updated>2022-10-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[애플리케이션을 구성하는 패턴]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="도메인-주도-설계-철저-입문">도메인 주도 설계 철저 입문<a href="https://clud.me/blog/ddd-introduction#%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%A3%BC%EB%8F%84-%EC%84%A4%EA%B3%84-%EC%B2%A0%EC%A0%80-%EC%9E%85%EB%AC%B8" class="hash-link" aria-label="도메인 주도 설계 철저 입문에 대한 직접 링크" title="도메인 주도 설계 철저 입문에 대한 직접 링크" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><a href="https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=252622256" target="_blank" rel="noopener noreferrer" class="">도메인 주도 설계 철저 입문</a> 을 보고 간단하게 정리한 내용이다.<br>
이 책을 읽어보는것을 추천한다.</p></div></div>
<ul>
<li class="">지식 표현을 위한 패턴
<ul>
<li class="">값 객체</li>
<li class="">엔티티</li>
<li class="">도메인 서비스</li>
</ul>
</li>
<li class="">애플리케이션을 구성하는 패턴
<ul>
<li class="">리포지터리</li>
<li class="">애플리케이션 서비스</li>
<li class="">팩토리</li>
</ul>
</li>
<li class="">지식 표현을 위한 고급 패턴
<ul>
<li class="">애그리게이트</li>
<li class="">명세</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="값-객체-value-object">값 객체 (Value Object)<a href="https://clud.me/blog/ddd-introduction#%EA%B0%92-%EA%B0%9D%EC%B2%B4-value-object" class="hash-link" aria-label="값 객체 (Value Object)에 대한 직접 링크" title="값 객체 (Value Object)에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>프로그래밍 언어에는 원시 데이터 타입(Primitive Type) 이 있고, 이 타입만 사용해서 개발이 가능하지만, 필요에 따라서 직접 타입을 정의해야 할 때가 있다</p>
</li>
<li class="">
<p>DDD 에서는 원시 타입만을 사용하지 않고, 도메인에 맞는 객체로 정의해서 사용한다</p>
</li>
<li class="">
<p>객체 자체를 하나의 값으로써 취급하기 때문에 <code>값 객체</code> 라고 부른다.</p>
</li>
<li class="">
<p>예시</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">FullName</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> firstName</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> lastName</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">firstName</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> lastName</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">firstName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> firstName</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">lastName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> lastName</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="성질">성질<a href="https://clud.me/blog/ddd-introduction#%EC%84%B1%EC%A7%88" class="hash-link" aria-label="성질에 대한 직접 링크" title="성질에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">불변이다</li>
<li class="">교환 가능하다</li>
<li class="">등가성을 비교할 수 있다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="장점">장점<a href="https://clud.me/blog/ddd-introduction#%EC%9E%A5%EC%A0%90" class="hash-link" aria-label="장점에 대한 직접 링크" title="장점에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">표현력이 증가된다</li>
<li class="">무결성이 유지된다</li>
<li class="">잘못된 대입을 방지한다</li>
<li class="">로직이 흩어지는걸 방지한다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="정리">정리<a href="https://clud.me/blog/ddd-introduction#%EC%A0%95%EB%A6%AC" class="hash-link" aria-label="정리에 대한 직접 링크" title="정리에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">원시 타입만으로 개발을 할 수 있지만, 범용적이기 때문에 도메인에 맞게 표현하기 어렵다
<ul>
<li class="">값 객체를 사용하면 좀 더 명확하게 표현할 수 있다</li>
</ul>
</li>
<li class="">중복 코드를 방지할 수 있고, 중요한 로직을 값 객체에 모아둘 수 있다</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="엔티티-entity">엔티티 (Entity)<a href="https://clud.me/blog/ddd-introduction#%EC%97%94%ED%8B%B0%ED%8B%B0-entity" class="hash-link" aria-label="엔티티 (Entity)에 대한 직접 링크" title="엔티티 (Entity)에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>엔티티는 도메인 모델을 구현한 도메인 객체를 의미한다.</p>
<ul>
<li class="">값 객체와 달리 생애주기를 가지고 있고, 식별자를 가지고 있다</li>
<li class="">생애주기를 갖고 있지 않거나, 생애주기가 무의미하면 값 객체로 다루는것이 좋다</li>
</ul>
</li>
<li class="">
<p>값 객체는 값만 같으면 동일한 데이터로 취급하지만, 엔티티는 식별자가 같아야 같은 데이터로 취급한다</p>
</li>
<li class="">
<p>예시</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserId</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> value</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> value</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> name</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="성질-1">성질<a href="https://clud.me/blog/ddd-introduction#%EC%84%B1%EC%A7%88-1" class="hash-link" aria-label="성질에 대한 직접 링크" title="성질에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">가변이다</li>
<li class="">속성이 같아도 구분할 수 있다</li>
<li class="">동일성을 통해 구별된다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="정리-1">정리<a href="https://clud.me/blog/ddd-introduction#%EC%A0%95%EB%A6%AC-1" class="hash-link" aria-label="정리에 대한 직접 링크" title="정리에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">도메인에 대한 내용이 한 곳에 모여있기 때문에 도메인을 이해하는데 도움이 된다</li>
<li class="">도메인 요구 사항이 변경된 경우 반영하기 쉽다</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="도메인-서비스-domain-service">도메인 서비스 (Domain Service)<a href="https://clud.me/blog/ddd-introduction#%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%84%9C%EB%B9%84%EC%8A%A4-domain-service" class="hash-link" aria-label="도메인 서비스 (Domain Service)에 대한 직접 링크" title="도메인 서비스 (Domain Service)에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">값 객체나 엔티티는 도메인의 행동을 정의할 수 있지만, 도메인 모델이 스스로 해결하기 부자연스러운 경우 도메인 서비스를 이용해서 해결한다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="예시">예시<a href="https://clud.me/blog/ddd-introduction#%EC%98%88%EC%8B%9C" class="hash-link" aria-label="예시에 대한 직접 링크" title="예시에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>중복된 이메일은 등록할 수 없다는 도메인 규칙이 있을 경우 이 행위 자체를 도메인 모델에 담기에는 부자연스럽다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>이런 경우 도메인 서비스를 이용하면 자연스럽게 해결할 수 있다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserDomainService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> userDomainService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">UserDomainService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">userDomainService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="주의사항">주의사항<a href="https://clud.me/blog/ddd-introduction#%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD" class="hash-link" aria-label="주의사항에 대한 직접 링크" title="주의사항에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>도메인 서비스로 대다수의 로직들을 작성할 수 있지만, 도메인 서비스는 도메인 모델에서 처리하기 부자연스러운 처리로만 제한해서 작성해야 한다</p>
</li>
<li class="">
<p>도메인 서비스를 남용하면 데이터와 행위가 여러군데로 흩어지기 때문에 도메인 모델의 유연성에 문제가 생길 수 있다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserDomainService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">changeEmail</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">email</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'이메일은 최소 1글자 이상이어야 한다.'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">email </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> email</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</li>
<li class="">
<p><strong>가능한 도메인 모델에 행위를 정의하고 도메인 서비스는 피하는것이 좋다</strong></p>
</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="리포지터리-repository">리포지터리 (Repository)<a href="https://clud.me/blog/ddd-introduction#%EB%A6%AC%ED%8F%AC%EC%A7%80%ED%84%B0%EB%A6%AC-repository" class="hash-link" aria-label="리포지터리 (Repository)에 대한 직접 링크" title="리포지터리 (Repository)에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">리포지터리는 도메인 객체를 저장하고 복원하는 역할을 담당한다</li>
<li class="">리포지토리의 책임은 객체의 퍼시스턴시까지이다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="예시-1">예시<a href="https://clud.me/blog/ddd-introduction#%EC%98%88%EC%8B%9C-1" class="hash-link" aria-label="예시에 대한 직접 링크" title="예시에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserRepository</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">findOne</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">findOneByEmail</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		 </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApplicationService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">createUser</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> userRepository </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">UserRepository</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">email</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">userService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">UserRepository</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="정리-2">정리<a href="https://clud.me/blog/ddd-introduction#%EC%A0%95%EB%A6%AC-2" class="hash-link" aria-label="정리에 대한 직접 링크" title="정리에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">ORM 에서 사용하는 엔티티와 도메인에서 얘기하는 엔티티는 완전 다른 객체이다
<ul>
<li class="">도메인의 엔티티와 ORM 에서 얘기하는 엔티티를 분리하지 않을 경우 특정 기술에 종속되거나 DB 와 코드가 결합되어 수정하기 어려워진다</li>
</ul>
</li>
<li class="">리포지터리는 객체의 저장, 복원만 담당하기 때문에 그 이상의 역할을 담아서는 안된다
<ul>
<li class="">구체적인 구현보다는 인터페이스로 작성해두면 특정 인프라스트럭처에 의존하지 않게 작성할 수 있다</li>
</ul>
</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="애플리케이션-서비스">애플리케이션 서비스<a href="https://clud.me/blog/ddd-introduction#%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%9C%EB%B9%84%EC%8A%A4" class="hash-link" aria-label="애플리케이션 서비스에 대한 직접 링크" title="애플리케이션 서비스에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">애플리케이션 서비스는 유스케이스를 구현한다
<ul>
<li class="">애플리케이션은 이용자의 목적을 해결하기 위한 프로그램을 의미한다</li>
<li class="">애플리케이션 서비스는 사용자가 원하는 기능을 구현하기위해 도메인 서비스, 리포지터리, 도메인 객체 등을 조합해서 수행한다</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="예시-2">예시<a href="https://clud.me/blog/ddd-introduction#%EC%98%88%EC%8B%9C-2" class="hash-link" aria-label="예시에 대한 직접 링크" title="예시에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">유스케이스 예시
<ul>
<li class="">사용자 등록하기</li>
<li class="">사용자 정보 수정하기</li>
</ul>
</li>
</ul>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">GetUserDto</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserApplicationService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> userRepository</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserRepository</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> userDomainService</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserDomainService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">email</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">userDomainService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'이미 가입된 사용자입니다'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findOneByEmail</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">email</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'유저 정보가 없습니다'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">GetUserDto</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">email</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="정리-3">정리<a href="https://clud.me/blog/ddd-introduction#%EC%A0%95%EB%A6%AC-3" class="hash-link" aria-label="정리에 대한 직접 링크" title="정리에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>도메인 객체를 직접 공개하는 경우 외부에서 데이터를 조작할 수 있기 때문에 직접 노출하지 않고 DTO (Data Transfer Object) 를 만들어서 전달하는것을 권장한다</p>
</li>
<li class="">
<p>데이터를 변경하는 경우 파라미터로 직접 다 받는것보다는 커맨드 객체를 만들어서 받는것이 좋다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UpdateUserCommand</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> email</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserApplicationService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">update</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">command</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UpdateUserCommand</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>애플리케이션 서비스는 도메인 객체가 수행하는 작업들을 조율하기만 해야 하며, 도메인 규칙이 노출되지 않게 해야한다</p>
</li>
<li class="">
<p>애플리케이션 서비스를 작성할 때는 응집도에 신경을 쓰는것이 바람직하다</p>
<ul>
<li class="">사용자와 관련된 유스케이스라고 해서 꼭 한 클래스에 모아둘 필요는 없다</li>
<li class="">유스케이스마다 클래스를 반드시 분리할 필요도 없지만, 클래스를 구성하는 변수와 메소드가 적절히 대응되어 있는지 검토해보면 좋다</li>
</ul>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserRegisterService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserDeleteService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>서비스는 어떠한 영역에도 존재할 수 있으며 상태를 가지고 있으면 안된다</p>
<ul>
<li class="">상태를 가지고 있을 경우 복잡성이 증가하고 혼란스럽게 만들 수 있기 때문에 무상태를 유지할 수 있는 방법을 찾아보는것이 좋다</li>
</ul>
</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="팩토리-패턴-factory-pattern">팩토리 패턴 (Factory Pattern)<a href="https://clud.me/blog/ddd-introduction#%ED%8C%A9%ED%86%A0%EB%A6%AC-%ED%8C%A8%ED%84%B4-factory-pattern" class="hash-link" aria-label="팩토리 패턴 (Factory Pattern)에 대한 직접 링크" title="팩토리 패턴 (Factory Pattern)에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>팩토리는 객체를 만드는 지식에 특화된 객체이다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserName</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserFactory</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">UserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token comment" style="color:#999988;font-style:italic">// ...);</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>객체의 생성 과정이 복잡하거나, 데이터베이스의 식별키 (Primary key) 를 연동해서 ID 에 부여해야할 때 사용할 수 있다</p>
</li>
<li class="">
<p>팩토리는 클래스 자체가 아니라 메서드가 역할을 하는 경우도 있다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Circle</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> userId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> CircleName</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">createCircle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">circleName</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> CircleName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Circle </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Circle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> circleName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>객체의 생성 절차가 간단하다면 생성자를 통해서 만드는것이 더 낫다</p>
</li>
<li class="">
<p>팩토리를 이용해 객체 생성 절차를 캡슐화하는 것도 로직의 의도를 더 명확히 드러내면서 유연성을 확보할 수 있는 좋은 방법이다</p>
</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-무결성-보장">데이터 무결성 보장<a href="https://clud.me/blog/ddd-introduction#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%AC%B4%EA%B2%B0%EC%84%B1-%EB%B3%B4%EC%9E%A5" class="hash-link" aria-label="데이터 무결성 보장에 대한 직접 링크" title="데이터 무결성 보장에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">데이터의 무결성을 보장하기 위해서는 여러가지 방법들이 있다</li>
<li class="">데이터베이스 유니크 인덱스 제약조건(Unique Index Constraint)
<ul>
<li class="">강력하게 제한할 수 이씾만, 코드에 관련된 내용이 없기 때문에 알 수 없다</li>
<li class="">유일 키 제약 기능은 특정 데이터베이스의 기술이기 때문에 의존성이 생긴다</li>
</ul>
</li>
<li class="">데이터베이스 트랜잭션
<ul>
<li class="">트랜잭션은 서로 의존적인 조작을 한꺼번에 완료하거나 취소하는 방법으로 무결성을 지킨다</li>
<li class="">관점 지향 프로그래밍 (AOP, Aspect Oriented Programming)</li>
<li class="">유닛 오브 워크 (UOW, Unit Of Work)
<ul>
<li class="">어떤 객체의 변경 사항을 기록하는 객체이다</li>
<li class="">퍼시스턴시 대상이 되는 객체의 생성, 변경, 삭제 등의 모든 동작이 모두 유닛오브워크를 통하게 된다</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="애그리거트-aggregate">애그리거트 (Aggregate)<a href="https://clud.me/blog/ddd-introduction#%EC%95%A0%EA%B7%B8%EB%A6%AC%EA%B1%B0%ED%8A%B8-aggregate" class="hash-link" aria-label="애그리거트 (Aggregate)에 대한 직접 링크" title="애그리거트 (Aggregate)에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">여러 개의 객체가 모여 한 가지 의미를 갖는 하나의 객체가 되는데, 이 객체들을 묶어서 표현하는것을 <strong>애그리거트(Aggregate)</strong> 라고 한다
<ul>
<li class="">애그리거트의 중점이 되는 객체를 <strong>애그리거트 루트 (Aggregate Root)</strong> 라고 한다</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="예시-3">예시<a href="https://clud.me/blog/ddd-introduction#%EC%98%88%EC%8B%9C-3" class="hash-link" aria-label="예시에 대한 직접 링크" title="예시에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserId</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">consturctor</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> value</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">UserName</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> value</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserId</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserName</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<ul>
<li class="">위의 예시에서 <code>User</code> 가 애그리거트 루트 (Aggregate Root) 가 된다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="규칙">규칙<a href="https://clud.me/blog/ddd-introduction#%EA%B7%9C%EC%B9%99" class="hash-link" aria-label="규칙에 대한 직접 링크" title="규칙에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>애그리거트에 포함된 객체를 조작할 때는 항상 애그리거트 루트를 통해서 수정해야 한다</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> userName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">UserName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Claude"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> userName</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 이렇게 사용하면 안된다</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">changeName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">userName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 이렇게 사용해야 한다</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>데메테르 법칙</p>
<ul>
<li class="">객체 간의 메소드 호출에 질서를 부여하기 위한 가이드라인이다.</li>
<li class="">어떤 컨텍스트에서 다음 객체의 메서드만을 호출할 수 있게 제한한다
<ul>
<li class="">객체 자신</li>
<li class="">인자로 전달받은 객체</li>
<li class="">인스턴스 변수</li>
<li class="">해당 컨텍스트에서 직접 생성한 객체</li>
</ul>
</li>
</ul>
</li>
<li class="">
<p>객체 내부의 데이터는 함부로 외부에 공개해서는 안된다</p>
<ul>
<li class="">일반적으로는 리포리저티 객체 외에는 애그리거트 내부 데이터에 접근하지 않는 코드를 규칙으로 만들어 협의해서 한다</li>
<li class="">강제성을 두기 위해서는 노티피케이션 객체 (Notification Object) 를 이용한다</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="애그리거트-경계">애그리거트 경계<a href="https://clud.me/blog/ddd-introduction#%EC%95%A0%EA%B7%B8%EB%A6%AC%EA%B1%B0%ED%8A%B8-%EA%B2%BD%EA%B3%84" class="hash-link" aria-label="애그리거트 경계에 대한 직접 링크" title="애그리거트 경계에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">애그리거트의 경계를 정하는 원칙 중 가장 흔히 쓰이는 방법은 <strong>변경의 단위</strong>이다.
<ul>
<li class="">애그리거트에 대한 변경은 해당 애그리거트에 맡기고, 퍼시스턴시 요청도 애그리거트 단위로 해야 한다</li>
</ul>
</li>
<li class="">경계를 확실하게 하기 위해서는 객체 인스턴스 대신 식별자(id) 를 들고 있으면 된다
<ul>
<li class="">이 방법은 메모리를 절약하는 부수적인 효과가 있다</li>
</ul>
</li>
<li class="">애그리거트 (Aggregate) 당 리포지터리 (Repository) 를 1개씩 만든다
<ul>
<li class="">애그리거트 크기는 가능한 작게 정하는게 좋다</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="예시-4">예시<a href="https://clud.me/blog/ddd-introduction#%EC%98%88%EC%8B%9C-4" class="hash-link" aria-label="예시에 대한 직접 링크" title="예시에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Circle</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	users</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> User</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">	</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> user2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> circle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Circle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">circle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">circle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">circleRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">circle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">user2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">UserName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'New Name'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<ul>
<li class="">위 코드로 인해 circle 안에 있는 user2 의 데이터가 변경되었으나, circle 안에는 user2 가 변경된 상태로 저장되어 있지 않기 때문에 복원할 경우 이전 데이터로 불러온다</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="명세-specification">명세 (Specification)<a href="https://clud.me/blog/ddd-introduction#%EB%AA%85%EC%84%B8-specification" class="hash-link" aria-label="명세 (Specification)에 대한 직접 링크" title="명세 (Specification)에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">명세는 어떤 객체가 그 객체의 평가 기준을 만족하는지 판정하기 위한 객체이다
<ul>
<li class="">명세는 엔티티나 값 객체가 리포지터리를 다루지 않으면서도 문제를 해결할 수 있다</li>
<li class="">도메인 규칙은 도메인 객체 안에 정의되어야 한다</li>
</ul>
</li>
<li class="">명세는 단독으로 사용되기도 하지만 리포지터리와 조합해 사용할 수 있다
<ul>
<li class="">리포지터리에서 명세를 필터로 사용할 경우 항상 성능에 염두를 둬야 한다</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="예시-5">예시<a href="https://clud.me/blog/ddd-introduction#%EC%98%88%EC%8B%9C-5" class="hash-link" aria-label="예시에 대한 직접 링크" title="예시에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">CircleFullSepcification</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">readonly</span><span class="token plain"> userRepository</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> UserRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">isSatisfiedBy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">circle</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Circle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> users </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">circle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">members</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> users</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">user </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> user</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">isPremium</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="복잡한-쿼리는-읽기-모델로-처리">복잡한 쿼리는 읽기 모델로 처리<a href="https://clud.me/blog/ddd-introduction#%EB%B3%B5%EC%9E%A1%ED%95%9C-%EC%BF%BC%EB%A6%AC%EB%8A%94-%EC%9D%BD%EA%B8%B0-%EB%AA%A8%EB%8D%B8%EB%A1%9C-%EC%B2%98%EB%A6%AC" class="hash-link" aria-label="복잡한 쿼리는 읽기 모델로 처리에 대한 직접 링크" title="복잡한 쿼리는 읽기 모델로 처리에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">시스템의 애초 존재 의의는 사용자의 문제를 해결하는것이다
<ul>
<li class="">그 어떤 조건보다 이 조건이 최우선이다</li>
</ul>
</li>
<li class="">복잡한 읽기 작업에서 성능 문제가 우려된다면 이러한 부분에 한해 도메인 객체의 제약을 벗어나도 된다
<ul>
<li class="">페이지네이션, 복잡한 JOIN 쿼리 등</li>
</ul>
</li>
<li class="">쓰기 작업 (Command) 에서는 도메인 객체 등을 적극적으로 활용하지만, 읽기 작업 (Query) 에서는 그렇지 않은 경우가 많다
<ul>
<li class="">CQS (Command-Query Separation), CQRS (Command-Query Responsibility Segregation) 등 이 있다</li>
</ul>
</li>
<li class="">지연 실행 (Lazy Execution) 을 통해 리포지터리는 그대로 사용하면서 성능 문제를 해결할 수 있는 방법도 있다</li>
</ul>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">CircleSummaryService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">getSummaries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">query</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> GetCircleSummary</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> GetCircleSummariesResult </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="도메인 주도 설계" term="도메인 주도 설계"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[용어 정리]]></title>
        <id>https://clud.me/blog/kotlin-glossary</id>
        <link href="https://clud.me/blog/kotlin-glossary"/>
        <updated>2022-03-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[코틀린의 기본적인 함수(function) 은 fun 키워드를 사용한다]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="용어-정리">용어 정리<a href="https://clud.me/blog/kotlin-glossary#%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC" class="hash-link" aria-label="용어 정리에 대한 직접 링크" title="용어 정리에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="함수-vs-메서드">함수 vs 메서드<a href="https://clud.me/blog/kotlin-glossary#%ED%95%A8%EC%88%98-vs-%EB%A9%94%EC%84%9C%EB%93%9C" class="hash-link" aria-label="함수 vs 메서드에 대한 직접 링크" title="함수 vs 메서드에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>코틀린의 기본적인 함수(function) 은 <code>fun</code> 키워드를 사용한다</p>
<ul>
<li class="">톱레벨 함수</li>
<li class="">클래스의 멤버 함수</li>
<li class="">함수 내부의 지역 함수</li>
</ul>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드</summary><div><div class="collapsibleContent_i85q">
<!-- -->
<ul>
<li class="">
<p>기본적인 예시</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">double</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 톱레벨 함수</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> A </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">triple</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 멤버 함수</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">twelveTimes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Int </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 멤버 함수</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">fourTimes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">double</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">double</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 지역 함수</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">triple</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">fourTimes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>익명 함수</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> double </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 익명 함수</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> triple </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> int </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 람다 표현식</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 람다 표현식은 익명 함수를 더 짧게 표현한것</span><br></div></code></pre></div></div>
</li>
</ul>
</div></div></details>
</li>
<li class="">
<p><strong>메서드(method)</strong> 는 클래스와 연결된 함수이다</p>
<ul>
<li class="">멤버 함수는 해당 클래스와 연결되어 있으므로, 메서드이다</li>
<li class="">메서드를 호출하려면 클래스 인스턴스가 있어야 하며, 이를 활용해서 참조해야 한다</li>
<li class="">모든 메서드는 함수이다</li>
</ul>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드</summary><div><div class="collapsibleContent_i85q">
<!-- -->
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">IntWrapper</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doubled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> IntWrapper </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">IntWrapper</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 멤버 이면서 메서드</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> wrapper </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">IntWrapper</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> doubledWrapper </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> wrapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doubled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> doubledReference </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> IntWrapper</span><span class="token operator" style="color:#393A34">::</span><span class="token plain">doubled</span><br></div></code></pre></div></div>
</div></div></details>
</li>
<li class="">
<p>확장 함수를 메서드로 불러도 되는지에 대해서는 논란의 여지가 있지만, 확장 함수도 호출을 할 때 인스턴스가 필요하므로 이 책에서는 메서드로 본다.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드</summary><div><div class="collapsibleContent_i85q">
<!-- -->
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> IntWrapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">tripled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">IntWrapper</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> wrapper </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">IntWrapper</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> tripledWrapper </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> wrapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">tripled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token keyword" style="color:#00009f">package</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> tripledReference </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> IntWrapper</span><span class="token operator" style="color:#393A34">::</span><span class="token plain">tripled</span><br></div></code></pre></div></div>
</div></div></details>
</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="멤버-vs-확장">멤버 vs 확장<a href="https://clud.me/blog/kotlin-glossary#%EB%A9%A4%EB%B2%84-vs-%ED%99%95%EC%9E%A5" class="hash-link" aria-label="멤버 vs 확장에 대한 직접 링크" title="멤버 vs 확장에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p><strong>멤버(member)</strong> 는 클래스 내부에 정의된 요소를 의미한다</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드</summary><div><div class="collapsibleContent_i85q">
<!-- -->
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> surname</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> fullName</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    	</span><span class="token keyword" style="color:#00009f">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"</span><span class="token string-literal singleline interpolation interpolation-punctuation punctuation" style="color:#393A34">$</span><span class="token string-literal singleline interpolation expression">name</span><span class="token string-literal singleline string" style="color:#e3116c"> </span><span class="token string-literal singleline interpolation interpolation-punctuation punctuation" style="color:#393A34">$</span><span class="token string-literal singleline interpolation expression">surname</span><span class="token string-literal singleline string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">withSurname</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">surname</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    	</span><span class="token function" style="color:#d73a49">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> surname</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</div></div></details>
</li>
<li class="">
<p><strong>확장 (extension)</strong> 은 이미 존재하는 클래스에 추가하는 가짜 멤버 같은것이다</p>
<ul>
<li class="">확장은 클래스 외부에서 정의하지만, 일반적인 멤버처럼 사용할 수 있다</li>
</ul>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드 </summary><div><div class="collapsibleContent_i85q">
<!-- -->
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> User</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">officialFullName</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"</span><span class="token string-literal singleline interpolation interpolation-punctuation punctuation" style="color:#393A34">$</span><span class="token string-literal singleline interpolation expression">surname</span><span class="token string-literal singleline string" style="color:#e3116c">, </span><span class="token string-literal singleline interpolation interpolation-punctuation punctuation" style="color:#393A34">$</span><span class="token string-literal singleline interpolation expression">name</span><span class="token string-literal singleline string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> User</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">withName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">User</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">surname</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
</div></div></details>
</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="파라미터와-와규먼트">파라미터와 와규먼트<a href="https://clud.me/blog/kotlin-glossary#%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EC%99%80-%EC%99%80%EA%B7%9C%EB%A8%BC%ED%8A%B8" class="hash-link" aria-label="파라미터와 와규먼트에 대한 직접 링크" title="파라미터와 와규먼트에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class=""><strong>파라미터 (parameter)</strong> 는 함수 선언에 정의되어 있는 변수를 의미한다</li>
<li class=""><strong>아규먼트(argument)</strong> 는 함수로 전달되는 실질적인 값을 의미한다</li>
<li class="">제네릭으로 선언된 변할 수 있는 부분이 <strong>타입 파라미터</strong> 이다
<ul>
<li class="">그리고 실질적인 타입이 <strong>타입 아규먼트</strong> 이다</li>
</ul>
</li>
</ul>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드</summary><div><div class="collapsibleContent_i85q">
<!-- -->
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">randomString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">length</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 파라미터</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">randomString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 아규먼트</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">inline</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">reified</span><span class="token plain"> T</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">printName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 타입 파라미터</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">T</span><span class="token operator" style="color:#393A34">::</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">simpleName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    printName</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 타입 아규먼트</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</div></div></details>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="기본-생성자와-추가적인-생성자">기본 생성자와 추가적인 생성자<a href="https://clud.me/blog/kotlin-glossary#%EA%B8%B0%EB%B3%B8-%EC%83%9D%EC%84%B1%EC%9E%90%EC%99%80-%EC%B6%94%EA%B0%80%EC%A0%81%EC%9D%B8-%EC%83%9D%EC%84%B1%EC%9E%90" class="hash-link" aria-label="기본 생성자와 추가적인 생성자에 대한 직접 링크" title="기본 생성자와 추가적인 생성자에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>생성자는 객체를 만들 때 호출되는 특별한 타입의 함수이다.</p>
<ul>
<li class="">코틀린이 생성자를 함수처럼 다루고, 생성자 레퍼런스도 함수 타입이지만, 공식적으로는 서브루틴이다</li>
</ul>
</li>
<li class="">
<p>생성자는 일반적으로 객체를 설정할 때 사용되는데, 이러한 생성자를 <strong>기본 생성자 (primary constructor)</strong> 라고 한다</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드</summary><div><div class="collapsibleContent_i85q">
<!-- -->
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">SomeObject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> text</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">init</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Creating Object"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</div></div></details>
</li>
<li class="">
<p>추가로 다른 생성자를 만들어야 하는 경우가 있는데, 이를 <strong>추가적인 생성자 (secondary constructor)</strong> 라고 한다</p>
<ul>
<li class="">추가적인 생성자는 일반적으로 this 키워드를 활용해서 기본 생성자를 호출한다\</li>
</ul>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드</summary><div><div class="collapsibleContent_i85q">
<!-- -->
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">SomeObject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> text</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">date</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Date</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">date</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">init</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Creating Object"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</div></div></details>
</li>
<li class="">
<p>일반적으로 코틀린에서는 추가적인 생성자를 사욯알 일이 거의 없다</p>
<ul>
<li class="">기본 생성자 아규먼트의 다른 서브셋을 만들 때는 디폴트 아규먼트를 활용할 수 있다</li>
<li class="">다른 종류의 객체를 만들어야 할 때는 팩토리 메서드를 사용한다</li>
</ul>
</li>
<li class="">
<p>자바에서 사용하기 위해서 기본 생성자 아규먼트의 여러 서브셋을 만들어야 한다면, <code>@JvmOverloads</code> 와 같은 어노테이션을 활용해서 함수에 대한 오버로드를 간단하게 만들 수 있다</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>예시 코드</summary><div><div class="collapsibleContent_i85q">
<!-- -->
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> SomeObject </span><span class="token annotation builtin">@JvmOverloads</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> text</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">init</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Creating Object"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
</div></div></details>
</li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="Kotlin" term="Kotlin"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kafka Connect (1)]]></title>
        <id>https://clud.me/blog/kafka-connect-1</id>
        <link href="https://clud.me/blog/kafka-connect-1"/>
        <updated>2022-02-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Kafka Connect 는 외부 시스템에 연결하기 위한 프레임워크를 제공하는 KAFKA 의 오픈 소스 구성 요소이다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-connect">Kafka Connect<a href="https://clud.me/blog/kafka-connect-1#kafka-connect" class="hash-link" aria-label="Kafka Connect에 대한 직접 링크" title="Kafka Connect에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class="">Kafka Connect 는 외부 시스템에 연결하기 위한 프레임워크를 제공하는 KAFKA 의 오픈 소스 구성 요소이다.</li>
<li class="">Kafka Connect 를 사용하기 위해서는 클러스터를 계획하고 프로비저닝하고, 작업을 처리하고 부하에 따라 스케일링을 고려해야 한다.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="용어">용어<a href="https://clud.me/blog/kafka-connect-1#%EC%9A%A9%EC%96%B4" class="hash-link" aria-label="용어에 대한 직접 링크" title="용어에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class=""><strong>Connect</strong>: Connector 를 동작하게 하는 프로세스 (서버)</li>
<li class=""><strong>Connector</strong>: Data Source(DB) 의 데이터를 처리하는 소스가 들어있는 jar 파일</li>
<li class=""><strong>Source Connector</strong>: Producer 역할을 담당</li>
<li class=""><strong>Sink Connector</strong>: Consumer 역할을 담당</li>
<li class=""><strong>Standalone 모드</strong>: 하나의 Connect 만 사용하는 모드</li>
<li class=""><strong>Distributed 모드</strong>: 여러개의 Connect 를 한개의 클러스터로 묶어서 사용하는 모드
<ul>
<li class="">Connect 중 한개가 장애나도 나머지 Connect 들이 이어서 처리할 수 있음</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="설치-방법">설치 방법<a href="https://clud.me/blog/kafka-connect-1#%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95" class="hash-link" aria-label="설치 방법에 대한 직접 링크" title="설치 방법에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">직접 설치하는 방법도 있겠지만, 로컬에서 테스트로 필요하면 docker 로 띄울 수 있다</li>
<li class=""><strong>docker hub</strong>: <a href="https://hub.docker.com/r/confluentinc/cp-kafka-connect" target="_blank" rel="noopener noreferrer" class="">https://hub.docker.com/r/confluentinc/cp-kafka-connect</a></li>
<li class=""><strong>Guide</strong>
<ul>
<li class=""><a href="https://github.com/confluentinc/demo-scene/blob/master/kafka-connect-zero-to-hero/docker-compose.yml#L89-L101" target="_blank" rel="noopener noreferrer" class="">https://github.com/confluentinc/demo-scene/blob/master/kafka-connect-zero-to-hero/docker-compose.yml#L89-L101</a></li>
<li class=""><a href="https://docs.confluent.io/platform/current/installation/docker/development.html#add-connectors-or-software" target="_blank" rel="noopener noreferrer" class="">https://docs.confluent.io/platform/current/installation/docker/development.html#add-connectors-or-software</a></li>
<li class=""><a href="https://docs.confluent.io/5.0.0/installation/docker/docs/installation/connect-avro-jdbc.html#" target="_blank" rel="noopener noreferrer" class="">https://docs.confluent.io/5.0.0/installation/docker/docs/installation/connect-avro-jdbc.html#</a></li>
</ul>
</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">kafka-connect </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_BOOTSTRAP_SERVERS</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">localhost:29092 </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_REST_PORT</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">28083</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_GROUP_ID</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"quickstart-avro"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_CONFIG_STORAGE_TOPIC</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"quickstart-config"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_OFFSET_STORAGE_TOPIC</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"quickstart-offsets"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_STATUS_STORAGE_TOPIC</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"quickstart-status"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_STATUS_STORAGE_REPLICATION_FACTOR</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_KEY_CONVERTER</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"org.apache.kafka.connect.json.JsonConverter"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_VALUE_CONVERTER</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"org.apache.kafka.connect.json.JsonConverter"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_INTERNAL_KEY_CONVERTER</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"org.apache.kafka.connect.json.JsonConverter"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_INTERNAL_VALUE_CONVERTER</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"org.apache.kafka.connect.json.JsonConverter"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_REST_ADVERTISED_HOST_NAME</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"localhost"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_LOG4J_ROOT_LOGLEVEL</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">DEBUG </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">CONNECT_PLUGIN_PATH</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">/usr/share/java,/etc/kafka-connect/jars </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"> /tmp/quickstart/file:/tmp/quickstart </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	confluentinc/cp-kafka-connect:latest</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rest-api">REST API<a href="https://clud.me/blog/kafka-connect-1#rest-api" class="hash-link" aria-label="REST API에 대한 직접 링크" title="REST API에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Kafka Connect 는 REST API 를 사용해서 Connector 를 만들 수 있는 방법을 제공한다</li>
<li class=""><code>GET /connectors</code> : 커넥터 목록 조회</li>
<li class=""><code>GET /connectors/{name}</code> : <code>{name}</code> 커넥터 정보 조회</li>
<li class=""><code>GET /connectors/{name}/status</code> : 커넥터 상태 조회</li>
<li class=""><code>POST /connectors</code> : 커넥터 생성</li>
<li class=""><code>DELETE /connectors/{name}</code> : <code>{name}</code> 커넥터 삭제</li>
<li class=""><code>GET /connector-plugins</code> : 설치된 플러그인 목록 조회</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="debezium">Debezium<a href="https://clud.me/blog/kafka-connect-1#debezium" class="hash-link" aria-label="Debezium에 대한 직접 링크" title="Debezium에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class="">데이터베이스의 변경 사항을 캡처하여 애플리케이션에서 사용할 수 있도록 해주는 분산 서비스 집합이다.</li>
<li class="">CDC ( Change Data Capture ) 을 사용하여 데이터베이스의 변경 사항을 수집한다</li>
<li class="">모든 Low Level 변경을 Changed Event Stream 에 기록한다.
<ul>
<li class="">애플리케이션은 이 스트림을 통해 변경 이벤트들을 순서대로 읽는다</li>
</ul>
</li>
<li class="">Debezium 의 목표는 다양한 DBMS 들의 변경 사항을 캡처하고 비슷한 구조의 변경 이벤트들을 Producing 하는 Connector 라이브러리를 구축하는것이다.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="지원하는-커넥터">지원하는 커넥터<a href="https://clud.me/blog/kafka-connect-1#%EC%A7%80%EC%9B%90%ED%95%98%EB%8A%94-%EC%BB%A4%EB%84%A5%ED%84%B0" class="hash-link" aria-label="지원하는 커넥터에 대한 직접 링크" title="지원하는 커넥터에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">MySQL</li>
<li class="">MongoDB</li>
<li class="">PostgreSQL</li>
<li class="">Orcal</li>
<li class="">SQL Server</li>
<li class="">DB2</li>
<li class="">Cassandra</li>
<li class="">Vitess</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="특징">특징<a href="https://clud.me/blog/kafka-connect-1#%ED%8A%B9%EC%A7%95" class="hash-link" aria-label="특징에 대한 직접 링크" title="특징에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Debezium 은 Log Based CDC 이다.</li>
<li class="">모든 데이터 변경이 캡처된다</li>
<li class="">Data Model 변경이 필요 없다</li>
<li class="">변경 뿐만 아니라 삭제도 캡처한다</li>
<li class="">레코드의 과거 상태도 캡처가 가능하다.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="기능">기능<a href="https://clud.me/blog/kafka-connect-1#%EA%B8%B0%EB%8A%A5" class="hash-link" aria-label="기능에 대한 직접 링크" title="기능에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Snapshots: 커넥터가 시작될 때 데이터베이스의 현재 상태에 대한 초기 스냅샷을 생성할 수 있다.</li>
<li class="">Filters: 특정 테이블이나 컬럼의 변경만 캡처할 수 있다</li>
<li class="">Masking: 민감한 정보의 경우 특정 컬럼을 마스킹처리 할 수 있다</li>
<li class="">Message Transformation
<ul>
<li class="">Topic Routing
<ul>
<li class="">이 기능을 사용하면 토픽의 이름을 변경하거나, 여러개의 테이블의 변경사항을 하나의 토픽으로 전달할 수 있다</li>
</ul>
</li>
<li class="">New Record State Extraction</li>
<li class="">Outbox Event Router</li>
<li class="">Message Filtering</li>
<li class="">Content-Based Routing</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="아키텍처">아키텍처<a href="https://clud.me/blog/kafka-connect-1#%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98" class="hash-link" aria-label="아키텍처에 대한 직접 링크" title="아키텍처에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-connect-1">Kafka Connect<a href="https://clud.me/blog/kafka-connect-1#kafka-connect-1" class="hash-link" aria-label="Kafka Connect에 대한 직접 링크" title="Kafka Connect에 대한 직접 링크" translate="no">​</a></h4>
<p><img decoding="async" loading="lazy" alt="Kafka Connect (1)" src="https://clud.me/assets/images/image-1-600b7c3271ba72b42d499ae9b634c12f.png" width="1712" height="389" class="img_ev3q"></p>
<ul>
<li class="">Kafka Connect 는 Kafka Broker 와 별도의 서비스로 운영된다</li>
<li class="">기본적으로 한 테이블의 변경 사항은 하나의 토픽으로 전달된다</li>
<li class="">MySQL 의 경우 binlog 에 접근하여 데이터를 가져온다</li>
<li class="">PostgreSQL 의 경우 Logical Replication Stream 에서 데이터를 가져온다</li>
<li class="">Source Connector 에서 가져온 정보들을 Sink Connector 를 통해서 ElasticSearch, Redis, Data Warehouse 등에 반영할 수 있다.</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="debezium-server">Debezium Server<a href="https://clud.me/blog/kafka-connect-1#debezium-server" class="hash-link" aria-label="Debezium Server에 대한 직접 링크" title="Debezium Server에 대한 직접 링크" translate="no">​</a></h4>
<p><img decoding="async" loading="lazy" alt="Kafka Connect (1)" src="https://clud.me/assets/images/image-2-f4266fd5a5b83389a360c086fde86889.png" width="1025" height="490" class="img_ev3q"></p>
<ul>
<li class="">Kafka Connector 를 사용하지 않고 <a href="https://debezium.io/documentation/reference/stable/operations/debezium-server.html" target="_blank" rel="noopener noreferrer" class="">Debezium Server</a> 를 이용해서 사용할 수 있다.</li>
<li class="">Debezium Server 는 Source Connector 중 하나를 사용하여 Source Database 의 변경 사항을 캡처하도록 구성한다.</li>
<li class="">변경된 이벤트는 JSON, Apache Avro 와 같은 형식으로 직렬화 할 수 있으며 Kinesis, Google Pub/Sub, Redis 등에 메시지를 전달할 수 있다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="embedded-engine">Embedded Engine<a href="https://clud.me/blog/kafka-connect-1#embedded-engine" class="hash-link" aria-label="Embedded Engine에 대한 직접 링크" title="Embedded Engine에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Kafka Connect 를 사용하지 않고 Embedded Engine 을 사용하여 자바 애플리케이션 라이브러리로도 사용할 수 있다.
<ul>
<li class=""><a href="https://debezium.io/documentation/reference/stable/development/engine.html" target="_blank" rel="noopener noreferrer" class="">Embedded Engine</a> 은 변경 이벤트를 애플리케이션에서 바로 Consuming 하거나 변경 내역을 별도의 메시지 브로커(e.g Amazon Kinesis) 에 전달할 때 유용하다.</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="로그-기반의-cdc-의-장점">로그 기반의 CDC 의 장점<a href="https://clud.me/blog/kafka-connect-1#%EB%A1%9C%EA%B7%B8-%EA%B8%B0%EB%B0%98%EC%9D%98-cdc-%EC%9D%98-%EC%9E%A5%EC%A0%90" class="hash-link" aria-label="로그 기반의 CDC 의 장점에 대한 직접 링크" title="로그 기반의 CDC 의 장점에 대한 직접 링크" translate="no">​</a></h3>
<ol>
<li class="">모든 데이터를 캡처할 수 있다
<ul>
<li class="">로그 기반으로 데이터의 변경사항을 가져오게되면 애플리케이션에서는 정확한 순서대로 데이터의 변화를 감지할 수 있다.</li>
<li class="">폴링 기반의 데이터 변경 사항을 가져오게 될 경우 최신 데이터만 가져오게 되며, 다운타임이 발생 했을 때는 데이터를 못가져온다.</li>
</ul>
</li>
<li class="">CPU 부하가 적고, 지연 시간이 적다
<ul>
<li class="">쿼리를 주기적으로 요청하지 않아도 되기 때문에 CPU를 거의 사용하지 하지 않으며, 실시간에 가까운 데이터 변경에 대응할 수 있다.</li>
</ul>
</li>
<li class="">데이터 모델에 영향이 없다
<ul>
<li class="">폴링 기반의 CDC 는 마지막 폴링 이후 변경된 레코드를 식별하기 위해 <code>LAST_UPDATE_TIMESTAMP</code> 와 같은 정보들을 추가해야되지만, 로그 기반의 CDC 는 그런게 필요 없다.</li>
</ul>
</li>
<li class="">삭제된 데이터를 캡처할 수 있다.</li>
<li class="">이전 레코드의 상태와 메타 데이터를 캡처할 수 있다
<ul>
<li class="">데이터가 업데이트 되었을 때, 이전 상태의 레코드 상태를 가져올 수 있다</li>
<li class="">로그 기반 CDC 는 Schema Change Stream 을 제공하고 Transaction ID 또는 사용자가 특정 변경사항을 적용한 것과 같은 메타데이터를 가져올 수 있다.</li>
</ul>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="사용-방법">사용 방법<a href="https://clud.me/blog/kafka-connect-1#%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95" class="hash-link" aria-label="사용 방법에 대한 직접 링크" title="사용 방법에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://debezium.io/documentation/reference/stable/connectors/mysql.html" target="_blank" rel="noopener noreferrer" class="">Debezium connector for MySQL</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="msk-connector">MSK Connector<a href="https://clud.me/blog/kafka-connect-1#msk-connector" class="hash-link" aria-label="MSK Connector에 대한 직접 링크" title="MSK Connector에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class="">MSK Connector 는 Kafka Connect 를 좀 더 쉽게 사용할 수 있는 기능을 제공한다.</li>
<li class=""><code>21.02.18</code> 기준으로 Kafka Connect 2.7.1 버전을 사용하고 있다</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="제공하는-기능">제공하는 기능<a href="https://clud.me/blog/kafka-connect-1#%EC%A0%9C%EA%B3%B5%ED%95%98%EB%8A%94-%EA%B8%B0%EB%8A%A5" class="hash-link" aria-label="제공하는 기능에 대한 직접 링크" title="제공하는 기능에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">커넥터의 전송 상태 모니터링</li>
<li class="">하드웨어 패치</li>
<li class="">처량 변화에 맞춘 오토 스케일링</li>
<li class="">Kafka Connect 와 완벽한 호환 제공</li>
<li class="">MSK 외에 On-Demand Kafka Cluster 지원</li>
<li class="">그 외 사용하기 손쉽게 만들어주는 완전 관리형 서비스</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="msk-connector-아키텍처">MSK Connector 아키텍처<a href="https://clud.me/blog/kafka-connect-1#msk-connector-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98" class="hash-link" aria-label="MSK Connector 아키텍처에 대한 직접 링크" title="MSK Connector 아키텍처에 대한 직접 링크" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="Kafka Connect (1)" src="https://clud.me/assets/images/image-3-f264fd5923f4599dfd5b0827b97fedc2.webp" width="641" height="381" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="사용-방법-1">사용 방법<a href="https://clud.me/blog/kafka-connect-1#%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95-1" class="hash-link" aria-label="사용 방법에 대한 직접 링크" title="사용 방법에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://aws.amazon.com/ko/blogs/korea/introducing-amazon-msk-connect-stream-data-to-and-from-your-apache-kafka-clusters-using-managed-connectors/" target="_blank" rel="noopener noreferrer" class="">Amazon MSK Connect - Apache Kafka 클러스터로 데이터 전달 서비스 출시 | Amazon Web Services</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="Kafka" term="Kafka"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[CloudFront 로 Dynamic Contents 를 전송하는 이유]]></title>
        <id>https://clud.me/blog/cloudfront-dynamic-contents</id>
        <link href="https://clud.me/blog/cloudfront-dynamic-contents"/>
        <updated>2021-10-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[URL Pattern 을 이용해서 기본 모든 Request 는 Dynamic Content ( API 서버 ) 쪽으로 호출되게 한다]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cloudfront-로-동적-컨텐츠를-전송하는-이유">CloudFront 로 동적 컨텐츠를 전송하는 이유<a href="https://clud.me/blog/cloudfront-dynamic-contents#cloudfront-%EB%A1%9C-%EB%8F%99%EC%A0%81-%EC%BB%A8%ED%85%90%EC%B8%A0%EB%A5%BC-%EC%A0%84%EC%86%A1%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0" class="hash-link" aria-label="CloudFront 로 동적 컨텐츠를 전송하는 이유에 대한 직접 링크" title="CloudFront 로 동적 컨텐츠를 전송하는 이유에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-간편한-설정--simple-configuration-">1. 간편한 설정 ( Simple Configuration )<a href="https://clud.me/blog/cloudfront-dynamic-contents#1-%EA%B0%84%ED%8E%B8%ED%95%9C-%EC%84%A4%EC%A0%95--simple-configuration-" class="hash-link" aria-label="1. 간편한 설정 ( Simple Configuration )에 대한 직접 링크" title="1. 간편한 설정 ( Simple Configuration )에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">URL Pattern 을 이용해서 기본 모든 Request 는 Dynamic Content ( API 서버 ) 쪽으로 호출되게 한다</li>
<li class="">특정 패턴 (e.g <code>/error/*</code>, <code>/assets/*</code> ) 의 URL 들은 Static Content ( S3 ) 쪽으로 호출되게 한다.</li>
<li class="">이 모든 설정들은 CloudFront Behaviros 에서 간단하게 설정만 하면 된다</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-ddos-mitigation--waf">2. DDoS Mitigation + WAF<a href="https://clud.me/blog/cloudfront-dynamic-contents#2-ddos-mitigation--waf" class="hash-link" aria-label="2. DDoS Mitigation + WAF에 대한 직접 링크" title="2. DDoS Mitigation + WAF에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">CDN 을 사용하게 되면 자연스럽게 얻을 수 있는 장점으로 Attacker 가 Attack 하기 어렵다
<ul>
<li class="">공격하는 지역의 Edge 에 대해 공격이 가게 되기 때문이다</li>
</ul>
</li>
<li class="">특정 사이트에서 조사했을 때 80% 의 트래픽은 L3, L4 의 Flood Attack, 20% 의 트래픽은 L7 의 Valid HTTP Request 이다.
<ul>
<li class="">CloudFront 를 설정하면 약 80% 정도의 공격은 Origin 서버까지 요청이 되지 않기 때문에 자연스럽게 방어가 된다</li>
</ul>
</li>
<li class="">WAF ( Web Application Firewall )
<ul>
<li class="">CloudFront 와 WAF 를 사용하여 20% 트래픽 중 공격들을 탐지하고 방어할 수 있다</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-cost-saving">3. Cost Saving<a href="https://clud.me/blog/cloudfront-dynamic-contents#3-cost-saving" class="hash-link" aria-label="3. Cost Saving에 대한 직접 링크" title="3. Cost Saving에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">AWS 는 InBound 는 Free, OutBound 는 비용이 서비스마다 다 다름</li>
<li class="">S3, ELB 에서 CloudFront Edge 로 가는 OutBound 는 무료</li>
<li class="">기본적으로 계약에 따라 다를 수 있지만, CloudFront OutBound 비용은 저렴해진다 ( DataTrasnferOut Pricing )</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-speed-up">4. Speed Up<a href="https://clud.me/blog/cloudfront-dynamic-contents#4-speed-up" class="hash-link" aria-label="4. Speed Up에 대한 직접 링크" title="4. Speed Up에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>각 지역에 있는 사용자들은 Edge 로 요청을 하게되는데, Edge 하고 AWS Region 간의 네트워크는 Optimize 되어 있기 때문에 퍼블릭망을 이용하는것보다 훨씬 빠르다</p>
</li>
<li class="">
<p>AWS CDN Edge, AWS Network 는 내부적으로 최적화된 백본망을 이용하기 때문에 Public Network 를 사용하는것보다 훨씬 빠른 성능을 얻을 수 있다</p>
</li>
<li class="">
<p>CloudFront 랑 Origin 은 Keep Alive Connection 을 유지하고 있기 때문에 성능상 이점을 가질 수 있다</p>
<p><img decoding="async" loading="lazy" alt="CloudFront 로 Dynamic Contents 를 전송하는 이유" src="https://clud.me/assets/images/image-1-40854a48a1b26ae3b03f4351fdc50041.webp" width="1270" height="712" class="img_ev3q"></p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-shield-origin-contents">5. Shield Origin Contents<a href="https://clud.me/blog/cloudfront-dynamic-contents#5-shield-origin-contents" class="hash-link" aria-label="5. Shield Origin Contents에 대한 직접 링크" title="5. Shield Origin Contents에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Amazon S3
<ul>
<li class="">Object Access Identify ( OAI )</li>
<li class="">S3 에 직접 다운로드 하는 트래픽을 차단할 수 있음</li>
</ul>
</li>
<li class="">Custom Origin
<ul>
<li class="">Block by IP Address</li>
<li class="">ELB 로 직접 요청하는 트래픽은 차단할 수 있음</li>
<li class="">CloudFront 의 IP Range 는 Public 하게 공개하고 있기 때문에 Security Group 으로 CloudFront IP Range 만 허용하면됨</li>
<li class="">CloudFront 아이피 대역폭이 변경된 경우 Amazon SNS 로 전달하고 있기 때문에 AWS Lambda 와 연동하여 자동으로 업데이트할 수 있도록 구성할 수 있음</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="참고">참고<a href="https://clud.me/blog/cloudfront-dynamic-contents#%EC%B0%B8%EA%B3%A0" class="hash-link" aria-label="참고에 대한 직접 링크" title="참고에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://www.youtube.com/watch?v=pGnLH7C8dYk" target="_blank" rel="noopener noreferrer" class="">AWS CLOUD Gaming 2. CloudFront로 동적 컨텐츠를 전송하는 네가지 이유와 Aurora는 어떻게 다른가</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="AWS" term="AWS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[KAFKA 무작정 따라하기 (1)]]></title>
        <id>https://clud.me/blog/kafka-getting-started-1</id>
        <link href="https://clud.me/blog/kafka-getting-started-1"/>
        <updated>2021-04-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[최근에 플랫폼을 구축하다가 데이터베이스에서 변경된 데이터를 가져와야 할 필요가 생겨서 찾아보다가 Kafka + MongoDB Change Stream을 활용하면 되겠다는 생각이 들어 찾아보게 되었다.]]></summary>
        <content type="html"><![CDATA[
<p>최근에 플랫폼을 구축하다가 데이터베이스에서 변경된 데이터를 가져와야 할 필요가 생겨서 찾아보다가 Kafka + MongoDB Change Stream을 활용하면 되겠다는 생각이 들어 찾아보게 되었다.</p>
<p>Kafka는 기존부터 관심이 많았었지만, 사례들을 찾다 보니 더 좋을거 같다는 판단이 들어 클러스터를 띄워보기로 했다.</p>
<p>로컬 환경에서는 docker-compose를 사용하여 손쉽게 띄웠지만, 실제 AWS EC2 위에서 docker를 사용하지 않고 띄우려고 하다 보니 삽질하는 상황이 많이 생겨서 정리해두려고 한다.</p>
<p>Confluent Community License에 포함된 <strong>REST Proxy</strong>, <strong>ksqldB</strong>, <strong>Schema Registry</strong> 까지 적용해보려고 한다.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-무작정-따라하기">kafka 무작정 따라하기<a href="https://clud.me/blog/kafka-getting-started-1#kafka-%EB%AC%B4%EC%9E%91%EC%A0%95-%EB%94%B0%EB%9D%BC%ED%95%98%EA%B8%B0" class="hash-link" aria-label="kafka 무작정 따라하기에 대한 직접 링크" title="kafka 무작정 따라하기에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="기본-설치">기본 설치<a href="https://clud.me/blog/kafka-getting-started-1#%EA%B8%B0%EB%B3%B8-%EC%84%A4%EC%B9%98" class="hash-link" aria-label="기본 설치에 대한 직접 링크" title="기본 설치에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="openjdk-설치">openjdk 설치<a href="https://clud.me/blog/kafka-getting-started-1#openjdk-%EC%84%A4%EC%B9%98" class="hash-link" aria-label="openjdk 설치에 대한 직접 링크" title="openjdk 설치에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ cd /opt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ wget https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_linux-x64_bin.tar.gz</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ tar -zxvf openjdk-11+28_linux-x64_bin.tar.gz</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ sudo ln -s /opt/jdk-11 /usr/local/java</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="confluent-community-설치">confluent community 설치<a href="https://clud.me/blog/kafka-getting-started-1#confluent-community-%EC%84%A4%EC%B9%98" class="hash-link" aria-label="confluent community 설치에 대한 직접 링크" title="confluent community 설치에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ curl -O http://packages.confluent.io/archive/6.1/confluent-community-6.1.1.tar.gz</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ tar -zxvf confluent-community-6.1.1.tar.gz</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ mv confluent-6.1.1/ confluent</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ sudo ln -s /opt/confluent /usr/local/confluent</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="path-설정">PATH 설정<a href="https://clud.me/blog/kafka-getting-started-1#path-%EC%84%A4%EC%A0%95" class="hash-link" aria-label="PATH 설정에 대한 직접 링크" title="PATH 설정에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ sudo vim /etc/profile</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">export JAVA_HOME=/usr/local/java</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">export PATH=$PATH:$JAVA_HOME/bin:/usr/local/confluent/bin</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="설정-파일">설정 파일<a href="https://clud.me/blog/kafka-getting-started-1#%EC%84%A4%EC%A0%95-%ED%8C%8C%EC%9D%BC" class="hash-link" aria-label="설정 파일에 대한 직접 링크" title="설정 파일에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="varlibzookeepermyid">/var/lib/zookeeper/myid<a href="https://clud.me/blog/kafka-getting-started-1#varlibzookeepermyid" class="hash-link" aria-label="/var/lib/zookeeper/myid에 대한 직접 링크" title="/var/lib/zookeeper/myid에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">1</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>sudo sh -c "echo 1 &gt; /var/lib/zookeeper/myid"</code></li>
<li class=""><code>1</code> 부분은 각 zookeeper 서버마다 다르게 설정해야 한다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="etchosts">/etc/hosts<a href="https://clud.me/blog/kafka-getting-started-1#etchosts" class="hash-link" aria-label="/etc/hosts에 대한 직접 링크" title="/etc/hosts에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">0.0.0.0 zookeeper-1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">{PRIVATE-IP-1} zookeeper-2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">{PRIVATE-IP-2} zookeeper-3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">0.0.0.0 broker-1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">{PRIVATE-IP-2} broker-2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">{PRIVATE-IP-3} broker-3</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>sudo vim /etc/hosts</code> 명령어를 실행한 후 맨 아래에 내용을 추가한다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="usrlocalconfluentetckafkazookeeperproperties">/usr/local/confluent/etc/kafka/zookeeper.properties<a href="https://clud.me/blog/kafka-getting-started-1#usrlocalconfluentetckafkazookeeperproperties" class="hash-link" aria-label="/usr/local/confluent/etc/kafka/zookeeper.properties에 대한 직접 링크" title="/usr/local/confluent/etc/kafka/zookeeper.properties에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">dataDir=/var/lib/zookeeper</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">maxClientCnxns=0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">admin.enableServer=false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">initLimit=5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">syncLimit=2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">server.1=zookeeper-1:2888:3888</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">server.2=zookeeper-2:2888:3888</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">server.3=zookeeper-3:2888:3888</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="usrlocalconfluentetckafkaserverproperties">/usr/local/confluent/etc/kafka/server.properties<a href="https://clud.me/blog/kafka-getting-started-1#usrlocalconfluentetckafkaserverproperties" class="hash-link" aria-label="/usr/local/confluent/etc/kafka/server.properties에 대한 직접 링크" title="/usr/local/confluent/etc/kafka/server.properties에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">######### 각 서버마다 고유한 ID 값을 설정해야한다. #########</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">broker.id=0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">###################################################</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">listeners=INTERNAL://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># EC2 의 Public IP 를 설정해야 한다.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">advertised.listeners=INTERNAL://:19092,EXTERNAL://{MY-PUBLIC-IP}:9092</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL,INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">inter.broker.listener.name=INTERNAL</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># 토픽 자동 생성 옵션은 꺼두는게 좋다</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">auto.create.topics.enable=false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># 토픽 삭제 활성화</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">delete.topic.enable=true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">zookeeper.connect=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="usrlocalconfluentetckafka-restkafka-restproperties">/usr/local/confluent/etc/kafka-rest/kafka-rest.properties<a href="https://clud.me/blog/kafka-getting-started-1#usrlocalconfluentetckafka-restkafka-restproperties" class="hash-link" aria-label="/usr/local/confluent/etc/kafka-rest/kafka-rest.properties에 대한 직접 링크" title="/usr/local/confluent/etc/kafka-rest/kafka-rest.properties에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">zookeeper.connect=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="usrlocalconfluentetcschema-registryschema-registryproperties">/usr/local/confluent/etc/schema-registry/schema-registry.properties<a href="https://clud.me/blog/kafka-getting-started-1#usrlocalconfluentetcschema-registryschema-registryproperties" class="hash-link" aria-label="/usr/local/confluent/etc/schema-registry/schema-registry.properties에 대한 직접 링크" title="/usr/local/confluent/etc/schema-registry/schema-registry.properties에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">listeners=http://0.0.0.0:8081</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">kafkastore.connection.url=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">kafkastore.topic=_schemas</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="usrlocalconfluentetckafkaconnect-distributedproperties">/usr/local/confluent/etc/kafka/connect-distributed.properties<a href="https://clud.me/blog/kafka-getting-started-1#usrlocalconfluentetckafkaconnect-distributedproperties" class="hash-link" aria-label="/usr/local/confluent/etc/kafka/connect-distributed.properties에 대한 직접 링크" title="/usr/local/confluent/etc/kafka/connect-distributed.properties에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">bootstrap.servers=broker-1:9092,broker-2:9092,broker-3:9092</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">group.id=connect-connect-group</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">key.converter=org.apache.kafka.connect.storage.StringConverter</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">key.converter.schemas.enable=true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">value.converter=io.confluent.connect.avro.AvroConverter</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">value.converter.schemas.enable=true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">value.converter.schema.registry.url=http://kafka.private.ddocdoc.kr:8081</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">rest.host.name=0.0.0.0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">rest.port=8083</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="실행하기">실행하기<a href="https://clud.me/blog/kafka-getting-started-1#%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0" class="hash-link" aria-label="실행하기에 대한 직접 링크" title="실행하기에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="zookeeper">zookeeper<a href="https://clud.me/blog/kafka-getting-started-1#zookeeper" class="hash-link" aria-label="zookeeper에 대한 직접 링크" title="zookeeper에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>실행하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ zookeeper-server-start -daemon /usr/local/confluent/etc/kafka/zookeeper.properties</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>종료하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ zookeeper-server-stop</span><br></div></code></pre></div></div>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka">kafka<a href="https://clud.me/blog/kafka-getting-started-1#kafka" class="hash-link" aria-label="kafka에 대한 직접 링크" title="kafka에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>실행하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-server-start -daemon /usr/local/confluent/etc/kafka/server.properties</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>종료하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-server-stop</span><br></div></code></pre></div></div>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="schema-registry">schema-registry<a href="https://clud.me/blog/kafka-getting-started-1#schema-registry" class="hash-link" aria-label="schema-registry에 대한 직접 링크" title="schema-registry에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>실행하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ schema-registry-start -daemon /usr/local/confluent/etc/schema-registry/schema-registry.properties</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>종료하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ schema-registry-stop</span><br></div></code></pre></div></div>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-rest">kafka-rest<a href="https://clud.me/blog/kafka-getting-started-1#kafka-rest" class="hash-link" aria-label="kafka-rest에 대한 직접 링크" title="kafka-rest에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>실행하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-rest-start -daemon /usr/local/confluent/etc/kafka-rest/kafka-rest.properties</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>종료하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-rest-stop</span><br></div></code></pre></div></div>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-connect">kafka-connect<a href="https://clud.me/blog/kafka-getting-started-1#kafka-connect" class="hash-link" aria-label="kafka-connect에 대한 직접 링크" title="kafka-connect에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>실행하기</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ connect-distributed -daemon /usr/local/confluent/etc/kafka/connect-distributed.properties</span><br></div></code></pre></div></div>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="주의사항">주의사항<a href="https://clud.me/blog/kafka-getting-started-1#%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD" class="hash-link" aria-label="주의사항에 대한 직접 링크" title="주의사항에 대한 직접 링크" translate="no">​</a></h3>
<p><del>confluent 가이드만 보고 따라하다가 방화벽 등을 생각하지 않아서 하루정도 삽질을 했다고 한다.</del></p>
<p>서버를 실행할 때 -daemon 옵션을 제거하고 실행해본 후, 정상 동작을 확인한 후 <code>-daemon</code> 옵션을 설정하는 것이 편하다.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="security-group">Security Group<a href="https://clud.me/blog/kafka-getting-started-1#security-group" class="hash-link" aria-label="Security Group에 대한 직접 링크" title="Security Group에 대한 직접 링크" translate="no">​</a></h4>
<p>AWS EC2 위에 설치를 완료했다면, 실행하기 전에 반드시 Security Group을 확인해줘야 하며, 아래의 포트들이 열려있어야 한다.</p>
<p>연결은 되는데 console-consumer 혹은 console-producer를 사용할 때 <code>LEADER_NOT_AVAILABLE</code> 에러를 발견하게 되면 아래 포트들로 정상 통신이 가능한지 확인해봐야 한다.</p>
<ul>
<li class=""><code>TCP 2888</code>: zookeeper sync</li>
<li class=""><code>TCP 3888</code>: zookeeper leader</li>
<li class=""><code>TCP 2181</code>: zookeeper client</li>
<li class=""><code>TCP 9092</code>: kafka broker</li>
<li class=""><code>TCP 8082</code>: kafka-rest</li>
<li class=""><code>TCP 8083</code>: kafka-connect</li>
<li class=""><code>TCP 8081</code>: schema-registry</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cli-명령어">cli 명령어<a href="https://clud.me/blog/kafka-getting-started-1#cli-%EB%AA%85%EB%A0%B9%EC%96%B4" class="hash-link" aria-label="cli 명령어에 대한 직접 링크" title="cli 명령어에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-topics">kafka-topics<a href="https://clud.me/blog/kafka-getting-started-1#kafka-topics" class="hash-link" aria-label="kafka-topics에 대한 직접 링크" title="kafka-topics에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">// 토픽 생성</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-topics --create --zookeeper zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 --topic test-1 --partitions 1 --replication-factor 3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">// 토픽 목록 조회</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-topics --list --zookeeper zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">// 토픽 조회</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-topics --describe --zookeeper zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 --topic test-1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">// 토픽 삭제</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-topics --delete --zookeeper {IP}:2181 --topic test-1</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-console-consumer">kafka-console-consumer<a href="https://clud.me/blog/kafka-getting-started-1#kafka-console-consumer" class="hash-link" aria-label="kafka-console-consumer에 대한 직접 링크" title="kafka-console-consumer에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-console-consumer --bootstrap-server {IP}:9092 --topic test-1</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-console-producer">kafka-console-producer<a href="https://clud.me/blog/kafka-getting-started-1#kafka-console-producer" class="hash-link" aria-label="kafka-console-producer에 대한 직접 링크" title="kafka-console-producer에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-console-producer --bootstrap-server {IP}:9092 --topic test-1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">&gt; Hello</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">&gt; World</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="kafka-connector-topic-만들기">kafka-connector topic 만들기<a href="https://clud.me/blog/kafka-getting-started-1#kafka-connector-topic-%EB%A7%8C%EB%93%A4%EA%B8%B0" class="hash-link" aria-label="kafka-connector topic 만들기에 대한 직접 링크" title="kafka-connector topic 만들기에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-topics --create --bootstrap-server {IP}:9092 --topic connect-configs --replication-factor 3 --partitions 1 --config cleanup.policy=compact</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-topics --create --bootstrap-server {IP}:9092 --topic connect-offsets --replication-factor 3 --partitions 50 --config cleanup.policy=compact</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ kafka-topics --create --bootstrap-server {IP}:9092 --topic connect-status --replication-factor 3 --partitions 10 --config cleanup.policy=compact</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="Kafka" term="Kafka"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Data Lake 란?]]></title>
        <id>https://clud.me/blog/what-is-data-lake</id>
        <link href="https://clud.me/blog/what-is-data-lake"/>
        <updated>2021-03-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[데이터 레이크는 정형 데이터, 반정형 데이터, 비정형 데이터 들을 구분하지 않고 모든 데이터를 저장한다]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="data-lake-란">Data Lake 란?<a href="https://clud.me/blog/what-is-data-lake#data-lake-%EB%9E%80" class="hash-link" aria-label="Data Lake 란?에 대한 직접 링크" title="Data Lake 란?에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="data-lake-란-무엇인가">Data Lake 란 무엇인가?<a href="https://clud.me/blog/what-is-data-lake#data-lake-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80" class="hash-link" aria-label="Data Lake 란 무엇인가?에 대한 직접 링크" title="Data Lake 란 무엇인가?에 대한 직접 링크" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p>엔터프라이즈 환경 내의 다양한 소스로부터 원본 데이터를 흭득, 처리, 분석 및 제공을 하는 거대한 규모의 데이터 저장소</p></div></div>
<ul>
<li class="">데이터 레이크는 <strong>정형 데이터</strong>, <strong>반정형 데이터</strong>, <strong>비정형 데이터</strong> 들을 구분하지 않고 모든 데이터를 저장한다</li>
<li class="">데이터 레이크는 온프레미스 또는 클라우드 에 구축될 수 있다.</li>
<li class="">AWS 의 경우 Amazon S3 를 주로 사용한다.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-레이크-장점">데이터 레이크 장점<a href="https://clud.me/blog/what-is-data-lake#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A0%88%EC%9D%B4%ED%81%AC-%EC%9E%A5%EC%A0%90" class="hash-link" aria-label="데이터 레이크 장점에 대한 직접 링크" title="데이터 레이크 장점에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">정보 기반의 의사 결정에 도움을 줄 수 있다.</li>
<li class="">데이터 포맷과 관계없이 한곳의 데이터 저장소에서 수집 &amp; 관리를 할 수 있다</li>
<li class="">데이터의 사일로 문제를 해결할 수 있다.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-레이크의-흐름">데이터 레이크의 흐름<a href="https://clud.me/blog/what-is-data-lake#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A0%88%EC%9D%B4%ED%81%AC%EC%9D%98-%ED%9D%90%EB%A6%84" class="hash-link" aria-label="데이터 레이크의 흐름에 대한 직접 링크" title="데이터 레이크의 흐름에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-데이터-수집">1. 데이터 수집<a href="https://clud.me/blog/what-is-data-lake#1-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%88%98%EC%A7%91" class="hash-link" aria-label="1. 데이터 수집에 대한 직접 링크" title="1. 데이터 수집에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">다양한 소스로부터 원본 데이터 그대로 ( 혹은 최소한의 변경으로 ) 데이터룰 수집한다.</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-데이터-처리">2. 데이터 처리<a href="https://clud.me/blog/what-is-data-lake#2-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B2%98%EB%A6%AC" class="hash-link" aria-label="2. 데이터 처리에 대한 직접 링크" title="2. 데이터 처리에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">수집한 데이터를 요구사항에 맞춰 가공하여 별도의 모델로 처리한다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-데이터-처리">3. 데이터 처리<a href="https://clud.me/blog/what-is-data-lake#3-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B2%98%EB%A6%AC" class="hash-link" aria-label="3. 데이터 처리에 대한 직접 링크" title="3. 데이터 처리에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">데이터 요구사항에 맞게 필요한 형태로 분석한다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-데이터-저장">4. 데이터 저장<a href="https://clud.me/blog/what-is-data-lake#4-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%80%EC%9E%A5" class="hash-link" aria-label="4. 데이터 저장에 대한 직접 링크" title="4. 데이터 저장에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">분석된 데이터를 적합한 데이터 저장소에 저장한다.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-레이크-요구사항">데이터 레이크 요구사항<a href="https://clud.me/blog/what-is-data-lake#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A0%88%EC%9D%B4%ED%81%AC-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD" class="hash-link" aria-label="데이터 레이크 요구사항에 대한 직접 링크" title="데이터 레이크 요구사항에 대한 직접 링크" translate="no">​</a></h3>
<ol>
<li class="">수집 데이터는 한 곳에 저장해야 한다.</li>
<li class="">저장 &amp; 처리 공간이 유연 ( Scalable ) 해야 한다.</li>
<li class="">데이터 생애 주기 ( Data life Cycle ) 정의가 가능해야 한다.</li>
<li class="">안정적으로 서비스가 운영되어야 한다.
<ul>
<li class="">운영용, 통계용 데이터베이스가 분리되어야 한다.</li>
</ul>
</li>
<li class="">데이터 관련 다양한 솔루션들과 호환이 쉬워야 한다.</li>
</ol>
<p><strong>데이터 웨어하우스 vs 데이터 레이크</strong></p>






























<table><thead><tr><th>이름</th><th>데이터 웨어하우스</th><th>데이터 레이크</th></tr></thead><tbody><tr><td>데이터</td><td>관계형 데이터</td><td>관계형 및 비관계형 데이터</td></tr><tr><td>스키마</td><td>데이터 웨어하우스 구현 전 설계됨 ( Schema on Write )</td><td>분석 시 사용됨 ( Schema on Read )</td></tr><tr><td>가격 / 성능</td><td>고비용 스토리지를 사용하여 빠른 결과물을 얻음</td><td>저비용 스토리지를 사용하여 쿼리 결과의 속도가 빠름</td></tr><tr><td>분석</td><td>배치 보고, 시각화 ( BI )</td><td>기계 학습, 예측 분석, 프로파일링 등</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-레이크---s3-설계-개념">데이터 레이크 - S3 설계 개념<a href="https://clud.me/blog/what-is-data-lake#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A0%88%EC%9D%B4%ED%81%AC---s3-%EC%84%A4%EA%B3%84-%EA%B0%9C%EB%85%90" class="hash-link" aria-label="데이터 레이크 - S3 설계 개념에 대한 직접 링크" title="데이터 레이크 - S3 설계 개념에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="tier-1-원본-데이터">Tier-1. 원본 데이터<a href="https://clud.me/blog/what-is-data-lake#tier-1-%EC%9B%90%EB%B3%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0" class="hash-link" aria-label="Tier-1. 원본 데이터에 대한 직접 링크" title="Tier-1. 원본 데이터에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">원본 데이터의 저장과 보관</li>
<li class="">최소한의 데이터 변환 작업만 진행</li>
<li class="">S3 의 Life Cycle 기능을 활용하여 S3-IA 혹은 Glacier 로 저장하여 저장 비용 감소</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="tier-2-분석용-데이터">Tier-2. 분석용 데이터<a href="https://clud.me/blog/what-is-data-lake#tier-2-%EB%B6%84%EC%84%9D%EC%9A%A9-%EB%8D%B0%EC%9D%B4%ED%84%B0" class="hash-link" aria-label="Tier-2. 분석용 데이터에 대한 직접 링크" title="Tier-2. 분석용 데이터에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Parquet / ORC 같은 Columnar 포맷 사용</li>
<li class="">파티션 정책에 따라 데이터 분산 및 유지 관리</li>
<li class="">분석을 위한 최적화</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="tier-3-특정-분석-목적-데이터--optional-">Tier-3. 특정 분석 목적 데이터 ( Optional )<a href="https://clud.me/blog/what-is-data-lake#tier-3-%ED%8A%B9%EC%A0%95-%EB%B6%84%EC%84%9D-%EB%AA%A9%EC%A0%81-%EB%8D%B0%EC%9D%B4%ED%84%B0--optional-" class="hash-link" aria-label="Tier-3. 특정 분석 목적 데이터 ( Optional )에 대한 직접 링크" title="Tier-3. 특정 분석 목적 데이터 ( Optional )에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">도메인 레벨로 데이터 마트 분리</li>
<li class="">Use Case 에 적합한 구성</li>
<li class="">특정 분석 방식에 적합한 데이터 변경 ( Machine Learning, AI )</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="참고">참고<a href="https://clud.me/blog/what-is-data-lake#%EC%B0%B8%EA%B3%A0" class="hash-link" aria-label="참고에 대한 직접 링크" title="참고에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://aws.amazon.com/ko/nosql/columnar/" target="_blank" rel="noopener noreferrer" class="">https://aws.amazon.com/ko/nosql/columnar/</a></li>
<li class=""><a href="https://en.wikipedia.org/wiki/Data_lake" target="_blank" rel="noopener noreferrer" class="">https://en.wikipedia.org/wiki/Data_lake</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="인프라" term="인프라"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AWS Glue 로컬에서 실행]]></title>
        <id>https://clud.me/blog/aws-glue-local</id>
        <link href="https://clud.me/blog/aws-glue-local"/>
        <updated>2021-02-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AWS Glue 를 테스트해보는데 AWS Console 에서 하기에는 비용이 발생하고, 화면이 좀 불편해서 로컬에다가 띄워서 사용하려고 한다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws-glue-로컬에서-실행">AWS Glue 로컬에서 실행<a href="https://clud.me/blog/aws-glue-local#aws-glue-%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-%EC%8B%A4%ED%96%89" class="hash-link" aria-label="AWS Glue 로컬에서 실행에 대한 직접 링크" title="AWS Glue 로컬에서 실행에 대한 직접 링크" translate="no">​</a></h2>
<p>AWS Glue 를 테스트해보는데 AWS Console 에서 하기에는 비용이 발생하고, 화면이 좀 불편해서 로컬에다가 띄워서 사용하려고 한다.</p>
<p>2020년 09월 08일에 Glue ETL Job 을 로컬환경에서 테스트할 수 있는 방법이 공개되었고, Docker 로 지원하기 때문에 손쉽게 설치할 수 있었다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="설치">설치<a href="https://clud.me/blog/aws-glue-local#%EC%84%A4%EC%B9%98" class="hash-link" aria-label="설치에 대한 직접 링크" title="설치에 대한 직접 링크" translate="no">​</a></h3>
<ol>
<li class="">
<p>Docker Image 를 내려받는다 ( Docker Hub 를 확인해 최신 이미지를 다운 받는다 )</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ docker pull amazon/aws-glue-libs:glue_libs_1.0.0_image_01</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>Container 를 실행시킨다</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ docker run -itd \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	-e AWS_REGION=ap-northeast-2 \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	-e AWS_PROFILE=default \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	-p 8080:8080 \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	-p 4040:4040 \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	-v ~/.aws:/root/.aws:ro \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	--name glue_zeppelin \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	amazon/aws-glue-libs:glue_libs_1.0.0_image_01 /home/zeppelin/bin/zeppelin.sh</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>웹페이지에 접속한다.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">http://127.0.0.1:8080</span><br></div></code></pre></div></div>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="참고">참고<a href="https://clud.me/blog/aws-glue-local#%EC%B0%B8%EA%B3%A0" class="hash-link" aria-label="참고에 대한 직접 링크" title="참고에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://aws.amazon.com/ko/blogs/big-data/developing-aws-glue-etl-jobs-locally-using-a-container/" target="_blank" rel="noopener noreferrer" class="">https://aws.amazon.com/ko/blogs/big-data/developing-aws-glue-etl-jobs-locally-using-a-container/</a></li>
<li class=""><a href="https://hub.docker.com/r/amazon/aws-glue-libs" target="_blank" rel="noopener noreferrer" class="">https://hub.docker.com/r/amazon/aws-glue-libs</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="AWS" term="AWS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Metabase 설치]]></title>
        <id>https://clud.me/blog/metabase-install</id>
        <link href="https://clud.me/blog/metabase-install"/>
        <updated>2021-02-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[데이터를 읽기 쉽게 시각화를 할 필요가 생겨서 여러가지 BI 도구들을 찾아봤다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="metabase">Metabase<a href="https://clud.me/blog/metabase-install#metabase" class="hash-link" aria-label="Metabase에 대한 직접 링크" title="Metabase에 대한 직접 링크" translate="no">​</a></h2>
<p>데이터를 읽기 쉽게 시각화를 할 필요가 생겨서 여러가지 BI 도구들을 찾아봤다.</p>
<p>제플린, 타블로, 파워BI 등 다양한 도구들이 있지만 그 중에서도 오픈소스이면서 사용하기 간단하고, 설치조차 너무나 간단한 Metabase 를 사용하여 설치법을 간단하게 정리해둔다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="설치">설치<a href="https://clud.me/blog/metabase-install#%EC%84%A4%EC%B9%98" class="hash-link" aria-label="설치에 대한 직접 링크" title="설치에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">개인 서버에다가 설치하기 때문에 SSL 인증서 등 다양한 처리를 자동으로 하기 위해 <code>bunkerized-nginx</code> 를 사용했다.</li>
<li class="">설정을 간소화 하기 위해 <code>docker-compose</code> 를 사용했다.</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="docker-composeyml">docker-compose.yml<a href="https://clud.me/blog/metabase-install#docker-composeyml" class="hash-link" aria-label="docker-compose.yml에 대한 직접 링크" title="docker-compose.yml에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-docker codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-docker codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">version: '3'</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">services:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  nginx:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    image: bunkerity/bunkerized-nginx</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    restart: always</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ports:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - target: 8080</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        published: 80</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - target: 8443</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        published: 443</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    volumes:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - ./letsencrypt:/etc/letsencrypt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - ./modsec-crs-confs:/modsec-crs-confs</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    environment:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - SERVER_NAME=clud.me</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - SERVE_FILES=no</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - DISABLE_DEFAULT_SERVER=yes</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - REDIRECT_HTTP_TO_HTTPS=yes</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - AUTO_LETS_ENCRYPT=yes</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - ALLOWED_METHODS=GET|POST|HEAD|PUT|DELETE|FETCH</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - USE_REVERSE_PROXY=yes</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - USE_GZIP=yes</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - USE_BROTLI=yes</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - USE_FAIL2BAN=no</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - USE_MODSECURITY=false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - USE_MODSECURITY_CRS=false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - REVERSE_PROXY_URL_1=/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - REVERSE_PROXY_HOST_1=http://metabase:3000/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - CONTENT_SECURITY_POLICY=CONTENT_SECURITY_POLICY-object-src 'none'; frame-ancestors 'self'; form-action 'self'; block-all-mixed-content; sandbox allow-forms allow-same-origin allow-scripts allow-popups allow-downloads; base-uri 'self';</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  metabase:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    image: metabase/metabase</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    restart: always</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ports:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - target: 3000</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        published: 3000</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    volumes:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - /home/ubuntu/metabase:/metabase-data</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    environment:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      - MB_DB_FILE=/metabase-data/metabase.db</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="modsec-crs-confs">modsec-crs-confs<a href="https://clud.me/blog/metabase-install#modsec-crs-confs" class="hash-link" aria-label="modsec-crs-confs에 대한 직접 링크" title="modsec-crs-confs에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">SecAction \</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> "id:900200,\</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  phase:1,\</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  nolog,\</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  pass,\</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  t:none,\</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  setvar:'tx.allowed_methods=GET HEAD POST PROPFIND DELETE PUT MKCOL MOVE COPY PROPPATCH REPORT'"</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="athena-연동">Athena 연동<a href="https://clud.me/blog/metabase-install#athena-%EC%97%B0%EB%8F%99" class="hash-link" aria-label="Athena 연동에 대한 직접 링크" title="Athena 연동에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Metabase 에서 Athena 를 사용하기 위해서는 JDBC 드라이버를 추가해줘야한다.</li>
</ul>
<div class="language-docker codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-docker codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> metabase/metabase:v0.37.3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ADD</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--chown</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">2000:2000</span><span class="token instruction"> </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">    https://github.com/dacort/metabase-athena-driver/releases/do</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>Dockerfile</code> 을 작성한 후 빌드하고 실행한다.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="레퍼런스">레퍼런스<a href="https://clud.me/blog/metabase-install#%EB%A0%88%ED%8D%BC%EB%9F%B0%EC%8A%A4" class="hash-link" aria-label="레퍼런스에 대한 직접 링크" title="레퍼런스에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://github.com/dacort/metabase-athena-driver" target="_blank" rel="noopener noreferrer" class="">https://github.com/dacort/metabase-athena-driver</a></li>
<li class=""><a href="https://github.com/bunkerity/bunkerized-nginx" target="_blank" rel="noopener noreferrer" class="">https://github.com/bunkerity/bunkerized-nginx</a></li>
<li class=""><a href="https://github.com/metabase/metabase" target="_blank" rel="noopener noreferrer" class="">https://github.com/metabase/metabase</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="데이터" term="데이터"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[OpenVPN 서버 구축]]></title>
        <id>https://clud.me/blog/openvpn-server</id>
        <link href="https://clud.me/blog/openvpn-server"/>
        <updated>2020-12-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[C19 가 심각해지면서 전사 재택 근무로 전환되었다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="openvpn-서버-구축">OpenVPN 서버 구축<a href="https://clud.me/blog/openvpn-server#openvpn-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95" class="hash-link" aria-label="OpenVPN 서버 구축에 대한 직접 링크" title="OpenVPN 서버 구축에 대한 직접 링크" translate="no">​</a></h2>
<p>C19 가 심각해지면서 전사 재택 근무로 전환되었다.</p>
<p>재택근무로 전환하게 되면서 내부 관리자 도구에 접속할 수 없는 문제가 발생하게 되었는데, 이를 해결하기 위해 VPN 서버를 구축하기로 했다.</p>
<p>VPN 을 구축하는데 큰 시간을 쏟을 수 없는 상황이기 때문에 <code>OpenVPN</code> 을 사용하기로 했고, 이 설치 조차 간단하게 하기 위해 <code>OpenVPN for Docker</code> 을 사용했다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step">Step<a href="https://clud.me/blog/openvpn-server#step" class="hash-link" aria-label="Step에 대한 직접 링크" title="Step에 대한 직접 링크" translate="no">​</a></h3>
<ol>
<li class="">
<p>AWS 에 EC2 Instance 를 1개 생성한다. ( <code>t3.micro</code> 혹은 <code>t3.small</code> 이면 충분하다. )</p>
<ul>
<li class="">Public Subnet 에 Ubuntu 20.04 를 설치</li>
<li class="">ElasticIP 할당</li>
</ul>
</li>
<li class="">
<p>Docker 를 설치한다.</p>
<ul>
<li class="">설치 메뉴얼: <a href="https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script" target="_blank" rel="noopener noreferrer" class="">https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script</a></li>
</ul>
</li>
<li class="">
<p>Docker 이미지를 다운로드 받는다</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> pull kylemanna/openvpn</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>OpenVPN 초기 설정을 진행한다.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$OVPN_DATA</span><span class="token plain">:/etc/openvpn </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> kylemanna/openvpn ovpn_genconfig </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> udp://</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> FIXME </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-N</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-d</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>{{ FIXME }}</code> 라고 적힌 부분을 실 도메인으로 설정한다.</li>
<li class="">만약 개인 도메인이 없는 경우, EC2 Public DNS 를 사용해도 된다.</li>
</ul>
</li>
<li class="">
<p>OpenVPN CA Certificate 와 비밀키를 생성한다.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$OVPN_DATA</span><span class="token plain">:/etc/openvpn </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-it</span><span class="token plain"> kylemanna/openvpn ovpn_initpki</span><br></div></code></pre></div></div>
<ul>
<li class="">명령어를 입력하면 <code>Passphrase</code> 를 입력한다.</li>
<li class=""><code>comman name</code> 은 기본값으로 사용한다.</li>
</ul>
</li>
<li class="">
<p>OpenVPN 서버를 실행한다.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$OVPN_DATA</span><span class="token plain">:/etc/openvpn </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1194</span><span class="token plain">:1194/udp </span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"ovpn"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--restart</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"always"</span><span class="token plain"> --cap-add</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">NET_ADMIN kylemanna/openvpn</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>클라이언트의 접속 정보를 생성한다.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$OVPN_DATA</span><span class="token plain">:/etc/openvpn </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-it</span><span class="token plain"> kylemanna/openvpn easyrsa build-client-full </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> FIXME </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> nopass</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>{{ FIXME }}</code> 라고 적힌 부분을 사용자 이름으로 변경한다.</li>
</ul>
</li>
<li class="">
<p>클라이언트의 접속 정보를 가져온다.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$OVPN_DATA</span><span class="token plain">:/etc/openvpn </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-it</span><span class="token plain"> kylemanna/openvpn ovpn_getclient </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> FIXME </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> FIXME </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">.ovpn</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>{{ FIXME }}</code> 라고 적힌 부분을 7번에서 지정한 사용자 이름으로 변경한다.</li>
</ul>
</li>
<li class="">
<p>EC2 보안 그룹을 설정한다.</p>
<ul>
<li class=""><code>UDP</code>  <code>1194</code> 포트를 열어둬야 한다.</li>
</ul>
</li>
<li class="">
<p>OpenVPN 클라이언트를 다운로드 받고 접속한다.</p>
<ul>
<li class="">MAC OS X 에서는 <code>Tunnelblick</code> 을 사용한다.</li>
</ul>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="명령어-팁">명령어 팁<a href="https://clud.me/blog/openvpn-server#%EB%AA%85%EB%A0%B9%EC%96%B4-%ED%8C%81" class="hash-link" aria-label="명령어 팁에 대한 직접 링크" title="명령어 팁에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>클라이언트 제거</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$OVPN_DATA</span><span class="token plain">:/etc/openvpn </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> kylemanna/openvpn ovpn_revokeclient </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> FIXME </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> remove</span><br></div></code></pre></div></div>
</li>
<li class=""></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="결론">결론<a href="https://clud.me/blog/openvpn-server#%EA%B2%B0%EB%A1%A0" class="hash-link" aria-label="결론에 대한 직접 링크" title="결론에 대한 직접 링크" translate="no">​</a></h3>
<p>OpenVPN for Docker 를 사용하면 5분만에 VPN 서버를 구축할 수 있다.</p>
<p>간단하게 VPN 서버를 띄워서 사용할 땐 좋지만, 제대로 사용하려면 AWS Client VPN 을 사용하는게 좋지 않을까 싶다.</p>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="인프라" term="인프라"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[EKS] istio + NLB 삽질기]]></title>
        <id>https://clud.me/blog/eks-istio-nlb</id>
        <link href="https://clud.me/blog/eks-istio-nlb"/>
        <updated>2020-11-12T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[회사에서 Kubernetes 를 적용하기로 결정했고, 모든 인프라를 AWS 위에서 구축하기 위해 EKS 를 사용하기로 했다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="istio--nlb-삽질기">istio + NLB 삽질기<a href="https://clud.me/blog/eks-istio-nlb#istio--nlb-%EC%82%BD%EC%A7%88%EA%B8%B0" class="hash-link" aria-label="istio + NLB 삽질기에 대한 직접 링크" title="istio + NLB 삽질기에 대한 직접 링크" translate="no">​</a></h2>
<p>회사에서 <code>Kubernetes</code> 를 적용하기로 결정했고, 모든 인프라를 AWS 위에서 구축하기 위해 <code>EKS</code> 를 사용하기로 했다.</p>
<p><code>EKS</code> 를 적용하면서 <code>istio</code> 와 <code>NLB</code> 를 적용하는데 어려워서 헤맸던 내용을 대략적으로만 정리한다.</p>
<p><code>istio</code>, <code>NLB</code> 에 대한 상세한 내용은 다른 포스트에서 정리할 예정이므로 여기서는 가장 삽질 했던 부분만 다룰 예정이다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="eks-에서-elb-를-사용하는-방법">EKS 에서 ELB 를 사용하는 방법<a href="https://clud.me/blog/eks-istio-nlb#eks-%EC%97%90%EC%84%9C-elb-%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95" class="hash-link" aria-label="EKS 에서 ELB 를 사용하는 방법에 대한 직접 링크" title="EKS 에서 ELB 를 사용하는 방법에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="clb-nlb-를-사용하여-서비스-노출">CLB, NLB 를 사용하여 서비스 노출<a href="https://clud.me/blog/eks-istio-nlb#clb-nlb-%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%85%B8%EC%B6%9C" class="hash-link" aria-label="CLB, NLB 를 사용하여 서비스 노출에 대한 직접 링크" title="CLB, NLB 를 사용하여 서비스 노출에 대한 직접 링크" translate="no">​</a></h4>
<p><code>EKS</code> 에서는 <code>ELB</code> 를 사용하려면 <code>Service</code> 를 <code>LoadBalancer</code> 로 지정하면 된다.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">svc</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> LoadBalancer</span><br></div></code></pre></div></div>
<p>이렇게 간단하게 설정하면 자동으로 <code>CLB</code> 가 생성된다.</p>
<p>하지만, 원했던건 <code>CLB</code> 가 아닌 <code>NLB</code> 이기 때문에 설정을 조금 수정했다</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">svc</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">annotations</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token key atrule" style="color:#00a4db">service.beta.kubernetes.io/aws-load-balancer-type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> nlb</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> LoadBalancer</span><br></div></code></pre></div></div>
<p><code>Service</code> 에 <code>annotation</code> 을 추가하면 <code>NLB</code> 가 Instance Target 으로 자동으로 생성된다.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="alb-를-사용하여-서비스-노출">ALB 를 사용하여 서비스 노출<a href="https://clud.me/blog/eks-istio-nlb#alb-%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%85%B8%EC%B6%9C" class="hash-link" aria-label="ALB 를 사용하여 서비스 노출에 대한 직접 링크" title="ALB 를 사용하여 서비스 노출에 대한 직접 링크" translate="no">​</a></h4>
<p><code>CLB</code> 와 <code>NLB</code> 는 별다른 설정 없이 가능했지만 ALB 는 <code>aws-load-balancer-controller</code> (구 AWS ALB Ingress Controller) 를 사용해야 한다.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">svc</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">---</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> extensions/v1beta1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Ingress</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">ing</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">annotations</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token key atrule" style="color:#00a4db">kubernetes.io/ingress.class</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> alb</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">alb.ingress.kubernetes.io/scheme</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> internet</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">facing</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token key atrule" style="color:#00a4db">rules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token key atrule" style="color:#00a4db">paths</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /*</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token key atrule" style="color:#00a4db">backend</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">					</span><span class="token key atrule" style="color:#00a4db">serviceName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> service</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">svc</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">					</span><span class="token key atrule" style="color:#00a4db">servicePort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="nlb-와-istio-를-적용하는-방법">NLB 와 istio 를 적용하는 방법<a href="https://clud.me/blog/eks-istio-nlb#nlb-%EC%99%80-istio-%EB%A5%BC-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95" class="hash-link" aria-label="NLB 와 istio 를 적용하는 방법에 대한 직접 링크" title="NLB 와 istio 를 적용하는 방법에 대한 직접 링크" translate="no">​</a></h3>
<p><code>AWS ALB Ingress Controller</code> 가 <code>AWS Load Balancer Controller</code> 로 변경되면서 <code>nlb-ip</code> 모드를 지원하기 시작했다.</p>
<p><code>Target Group</code> 에 모든 노드를 넣는것보다는 Ingress Gateway IP 만 대상 그룹에 적용되어 있는게 더 효율적이지 않을까 라는 생각이 들어서 적용했다.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> install.istio.io/v1alpha1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> IstioOperator</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> istiocontrolplane</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> istio</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">system</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">profile</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> default</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">components</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">ingressGateways</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> istio</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">ingressgateway</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"> </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> simple</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">ingressgateway</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">label</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">service.istio.io/canonical-name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> simple</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">ingressgateway</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">k8s</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">service</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">externalTrafficPolicy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Local</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">hpaSpec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">minReplicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">maxReplicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">service</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> https</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">443</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> helath</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15020</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15020</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> NodePort </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">serviceAnnotations</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">service.beta.kubernetes.io/aws-load-balancer-type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'nlb-ip'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">service.beta.kubernetes.io/aws-load-balancer-backend-protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">service.beta.kubernetes.io/aws-load-balancer-ssl-ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"443"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">service.beta.kubernetes.io/aws-load-balancer-ssl-cert</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"{REDACTED}"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">values</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">sidecarInjectorWebhook</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">rewriteAppHTTPProbe</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">gateways</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">istio-ingressgateway</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ClusterIP</span><br></div></code></pre></div></div>
<p><code>istio-operator.yaml</code>  파일을 정의한 아래의 명령어를 수행하면 istio-ingressgateway 와 simple-ingressgateway 가 생성되면서 <code>nlb-ip</code> 가 생성된다.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ istioctl </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> istio-operator.yaml</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="source-ip">SOURCE IP<a href="https://clud.me/blog/eks-istio-nlb#source-ip" class="hash-link" aria-label="SOURCE IP에 대한 직접 링크" title="SOURCE IP에 대한 직접 링크" translate="no">​</a></h4>
<p><code>nlb-ip</code> 모드를 사용하게 될 경우 내부 POD 에서는 Source IP 를 얻을 수 없고, POD 의 IP 정보가 넘어온다.</p>
<p>사용자의 IP 를 서비스에서 알아야 할 경우가 생길 수 있는 이런 경우 <code>envoy-filter</code> 만 추가하면 된다</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> networking.istio.io/v1alpha3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> EnvoyFilter</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> proxy</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">protocol</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> istio</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">system</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">workloadSelector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">istio</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ingressgateway</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">configPatches</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">applyTo</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> LISTENER</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">patch</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">operation</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> MERGE</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">listener_filters</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> envoy.filters.listener.proxy_protocol</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> envoy.filters.listener.tls_inspector</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="참고">참고<a href="https://clud.me/blog/eks-istio-nlb#%EC%B0%B8%EA%B3%A0" class="hash-link" aria-label="참고에 대한 직접 링크" title="참고에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/kubernetes-sigs/aws-load-balancer-controller" target="_blank" rel="noopener noreferrer" class="">kubernetes-sigs/aws-load-balancer-controller</a></li>
<li class=""><a href="https://github.com/aws/eks-charts/tree/master/stable/aws-load-balancer-controller" target="_blank" rel="noopener noreferrer" class="">aws/eks-charts</a></li>
<li class=""><a href="https://istio.io/latest/docs/setup/install/operator/" target="_blank" rel="noopener noreferrer" class="">Istio Operator Install</a></li>
<li class=""><a href="https://kubernetes.io/docs/tutorials/services/source-ip/" target="_blank" rel="noopener noreferrer" class="">Using Source IP</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="Kubernetes" term="Kubernetes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Scope]]></title>
        <id>https://clud.me/blog/javascript-scope</id>
        <link href="https://clud.me/blog/javascript-scope"/>
        <updated>2020-07-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[C, C++, Java, JavaScript 와 같이 대부분의 프로그램 언어들은 Lexical Scope ( 또는 Static Scope ) 를 사용하고 있다. Lexical Scope 의 반대 방식은 Dynamic Scope 가 있으며 Perl, B…]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="개요">개요<a href="https://clud.me/blog/javascript-scope#%EA%B0%9C%EC%9A%94" class="hash-link" aria-label="개요에 대한 직접 링크" title="개요에 대한 직접 링크" translate="no">​</a></h2>
<p><code>C</code>, <code>C++</code>, <code>Java</code>, <code>JavaScript</code> 와 같이 대부분의 프로그램 언어들은 Lexical Scope ( 또는 Static Scope ) 를 사용하고 있다. Lexical Scope 의 반대 방식은 Dynamic Scope 가 있으며 <code>Perl</code>, <code>Bash Shell</code> 등이 사용한다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="시작하기-전에">시작하기 전에<a href="https://clud.me/blog/javascript-scope#%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EC%A0%84%EC%97%90" class="hash-link" aria-label="시작하기 전에에 대한 직접 링크" title="시작하기 전에에 대한 직접 링크" translate="no">​</a></h3>
<p>아래의 코드를 실행하면 결과가 어떻게 출력될 지 생각해보자.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">wrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">wrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lexical-scope">Lexical Scope<a href="https://clud.me/blog/javascript-scope#lexical-scope" class="hash-link" aria-label="Lexical Scope에 대한 직접 링크" title="Lexical Scope에 대한 직접 링크" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p>Lexical Scope: use environment where function is defined.<br>
Dynamic Scope: use environment where function is called.</p></div></div>
<p>Lexical Scope는 변수나 함수가 <strong>정의</strong>된 곳에 따라 상위 스코프를 결정한다.</p>
<p>이 말을 조금 더 쉽게 풀어서 설명하면, 함수가 처음 선언된 순간 함수 내부의 변수는 스코프를 기준으로 가장 가까운 곳에 있는 변수를 참조하게 된다.</p>
<p>위의 코드를 예로 들어서 설명하면 <code>echo</code> 함수 안에 <code>age</code> 변수는 선언 시 가장 가까운 곳에 있는 전역 변수 <code>age</code>를 참조한다.</p>
<p><code>wrap</code> 함수 안에서 <code>age</code> 변수를 선언해도 <code>echo</code> 함수는 전역 변수인 <code>age</code>를 바라보고 있기 때문에 전역 변수 값인 <code>10</code> 이 출력된다.</p>
<p>위의 코드의 결과는 아래와 같다.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token number" style="color:#36acaa">30</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">10</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="function-scope">Function Scope<a href="https://clud.me/blog/javascript-scope#function-scope" class="hash-link" aria-label="Function Scope에 대한 직접 링크" title="Function Scope에 대한 직접 링크" translate="no">​</a></h4>
<p>함수 내부에서 선언한 변수는 함수 내에서 계속 유효하며, 함수 외부에서는 참조할 수 없다.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// ReferenceError: age is not defined</span><br></div></code></pre></div></div>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 결과 값</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">20</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">20</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="block-scope">Block Scope<a href="https://clud.me/blog/javascript-scope#block-scope" class="hash-link" aria-label="Block Scope에 대한 직접 링크" title="Block Scope에 대한 직접 링크" translate="no">​</a></h4>
<p>코드 블록 ( <code>{}</code> ) 내에0서 선언된 변수는 해당 블록에서만 유효하며, 외부 블록에서 참조할 수 없다.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 결과 값</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">20</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">10</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="var-vs-let">var vs let<a href="https://clud.me/blog/javascript-scope#var-vs-let" class="hash-link" aria-label="var vs let에 대한 직접 링크" title="var vs let에 대한 직접 링크" translate="no">​</a></h4>
<p>ES6 에서 <code>let, const</code> keyword 가 추가되었다. <code>var</code> , <code>let</code> 은 변수를 선언하는 keyword 이지만, 많은 부분에서 차이가 발생한다.</p>
<ul>
<li class="">
<p><code>var</code></p>
<ul>
<li class="">Function Scope</li>
<li class="">Hositing</li>
<li class="">중복 선언 가능</li>
</ul>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
<li class="">
<p><code>let</code></p>
<ul>
<li class="">
<p>Blcok Scope</p>
</li>
<li class="">
<p>No Hoisting</p>
</li>
<li class="">
<p>중복 선언 불가능</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// SyntaxError: Identifier 'age' has already been declared</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">echo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="참고">참고<a href="https://clud.me/blog/javascript-scope#%EC%B0%B8%EA%B3%A0" class="hash-link" aria-label="참고에 대한 직접 링크" title="참고에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let" target="_blank" rel="noopener noreferrer" class="">let</a></li>
<li class=""><a href="https://dev.to/sandy8111112004/javascript-introduction-to-scope-function-scope-block-scope-d11" target="_blank" rel="noopener noreferrer" class="">JavaScript: Introduction to Scope (function scope, block scope)</a></li>
<li class=""><a href="https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd" target="_blank" rel="noopener noreferrer" class="">⚡️⛓JavaScript Visualized: Scope (Chain)</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="JavaScript" term="JavaScript"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[이벤트 루프]]></title>
        <id>https://clud.me/blog/event-loop</id>
        <link href="https://clud.me/blog/event-loop"/>
        <updated>2020-03-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[JavaScript를 사용하다 보면 Single-Threaded 나 Event Loop 에 대한 내용을 자주 접하게 된다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="개요">개요<a href="https://clud.me/blog/event-loop#%EA%B0%9C%EC%9A%94" class="hash-link" aria-label="개요에 대한 직접 링크" title="개요에 대한 직접 링크" translate="no">​</a></h2>
<p>JavaScript를 사용하다 보면 <code>Single-Threaded</code> 나 <code>Event Loop</code> 에 대한 내용을 자주 접하게 된다.</p>
<p>여러 글을 읽다가 한번 정리해야겠다는 생각이 들어서 정리해보려고 한다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="시작하기-전에">시작하기 전에<a href="https://clud.me/blog/event-loop#%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EC%A0%84%EC%97%90" class="hash-link" aria-label="시작하기 전에에 대한 직접 링크" title="시작하기 전에에 대한 직접 링크" translate="no">​</a></h3>
<p>아래 코드를 실행하면 결과가 어떻게 출력될 지 생각해보자.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Main 1'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> interval </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setInterval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'interval 1'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'timeout 1'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token known-class-name class-name">Promise</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'promise 1'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'promise 2'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">clearInterval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">interval</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'timeout 2'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Main 2'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token known-class-name class-name">Promise</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'promise 3'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'promise 4'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="javascript-engine">JavaScript Engine<a href="https://clud.me/blog/event-loop#javascript-engine" class="hash-link" aria-label="JavaScript Engine에 대한 직접 링크" title="JavaScript Engine에 대한 직접 링크" translate="no">​</a></h2>
<p>자바스크립트 엔진은 <strong>Memory Heap</strong> 과 <strong>Call Stack</strong> 으로 구성되어 있다.</p>
<p>가장 유명한 것이 <a href="https://v8.dev/" target="_blank" rel="noopener noreferrer" class="">Google V8 Engine</a> 이다.</p>
<p>JavaScript는 <strong>Single-Threaded</strong> 이다. ( Call Stack을 1개만 사용한다 )</p>
<p>싱글 스레드는 한 번에 한 개의 작업만 실행할 수 있다.</p>
<p>이러한 특징 때문에 자바스크립트의 함수가 동작하는 방식을 <code>Run to Completion</code>이라고 한다.</p>
<p>일반적으로는 한 번에 한 작업만 실행할 수 있는 게 큰 문제가 되지 않지만, 한 개의 작업이 오래 걸리면 뒤에 있는 다른 작업이 실행이 안 되고 계속 지연된다.</p>
<ul>
<li class="">Memory Heap: 동적으로 생성된 객체 ( 인스턴스 ) 가 저장되는 영역</li>
<li class="">Call Stack: 코드가 실행될 때 쌓이는 영역 ( Stack 형태 )</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="task-queue">Task Queue<a href="https://clud.me/blog/event-loop#task-queue" class="hash-link" aria-label="Task Queue에 대한 직접 링크" title="Task Queue에 대한 직접 링크" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p>Event Queue == Task Queue == Message Queue ( 모두 같은 말 )</p></div></div>
<p>NodeJS 는 2개의 Queue( Macro Task, Micro Task )를 사용한다.</p>
<p>Macro Task를 1개 수행한 후 Micro Task Queue에 있는 모든 Task를 수행한다. ( 혹은 지정된 Max Count까지 수행한다. )</p>
<ul>
<li class="">Macro Task Queue
<ul>
<li class="">I/O</li>
<li class="">setInterval</li>
<li class="">setImmediate</li>
<li class="">setTimeout</li>
</ul>
</li>
<li class="">Micro Task Queue
<ul>
<li class="">process.nextTick</li>
<li class="">Promise</li>
<li class="">Object.observe</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="event-loop">Event Loop<a href="https://clud.me/blog/event-loop#event-loop" class="hash-link" aria-label="Event Loop에 대한 직접 링크" title="Event Loop에 대한 직접 링크" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p>Node.js 는 <a href="http://libuv.org/" target="_blank" rel="noopener noreferrer" class="">libuv</a> 를 사용한다.</p></div></div>
<p>이벤트 루프는 가능하면 언제나 시스템 커널에 Task를 넘겨서 Node.js 가 Non Blocking I/O 작업을 수행하도록 한다.</p>
<p>대부분의 커널은 Multi-Thread이기 때문에 백그라운드에서 여러 개의 Task를 수행할 수 있다. 이러한 작업 중 하나가 완료되면 커널이 Node.js 에게 알려줘서 Callback을 Poll Queue에 추가할 수 있도록 한다.</p>
<p>Event Queue는 총 7개가 있으며, 각 Queue를 Phase ( 단계 )라고 표현한다.</p>
<p>이벤트 루프가 실행하는 사이 Node.js 는 다른 비동기 I/O 나 Timer를 기다리고 있는지 확인하고, 없으면 종료한다.</p>
<p><img decoding="async" loading="lazy" alt="각 Phase 들은 Callback의 FIFO Queue를 가지고 있다." src="https://clud.me/assets/images/image-1-daab028cee2f734911d7f622f653f836.webp" width="1498" height="898" class="img_ev3q"></p>
<p><em>각 Phase 들은 Callback의 FIFO Queue를 가지고 있다.</em></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="timers">Timers<a href="https://clud.me/blog/event-loop#timers" class="hash-link" aria-label="Timers에 대한 직접 링크" title="Timers에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class=""><code>setTimeout</code>, <code>setInterval</code> Callback 이 실행되는 단계</li>
<li class="">Timer Phase에 Task를 넣는 것은 Poll Phase에서 실행</li>
<li class="">Timer Phase는 단지 시간 관련 함수를 실행</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="pending-callbacks">Pending Callbacks<a href="https://clud.me/blog/event-loop#pending-callbacks" class="hash-link" aria-label="Pending Callbacks에 대한 직접 링크" title="Pending Callbacks에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Loop의 반복으로 연기된 I/O Callback 들을 실행</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="idleprepare">idle/prepare<a href="https://clud.me/blog/event-loop#idleprepare" class="hash-link" aria-label="idle/prepare에 대한 직접 링크" title="idle/prepare에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">내부용으로만 사용</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="poll">Poll<a href="https://clud.me/blog/event-loop#poll" class="hash-link" aria-label="Poll에 대한 직접 링크" title="Poll에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">I/O 를 얼마나 오래 Block 해야 하고 Polling 해야 하는지 계산함</li>
<li class="">Poll Queue에 있는 이벤트를 처리함</li>
<li class="">Scheduling 된 타이머가 없으면
<ol>
<li class=""><code>Poll Queue가 비어있지 않다면</code> 이벤트 루프가 Queue를 처리하면서 다 처리하거나 최대치에 도달할 때까지 동기적으로 Callback을 실행함</li>
<li class=""><code>Poll Queue가 비어있다면</code>
<ul>
<li class=""><code>setImmediate</code> 가 스케줄링 되어 있다면 Poll Phase를 종료하고 Check Phase 로 넘어감</li>
<li class=""><code>setImmediate</code> 가 스케줄링 되어 있지 않으면 Callback이 Queue에 추가될 때까지 기다린 후 즉시 실행함</li>
</ul>
</li>
</ol>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="check">Check<a href="https://clud.me/blog/event-loop#check" class="hash-link" aria-label="Check에 대한 직접 링크" title="Check에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class=""><code>setImmediate</code> Callback 이 실행되는 단계</li>
<li class=""><code>Poll</code> 실행 직후 바로 실행됨</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="close">Close<a href="https://clud.me/blog/event-loop#close" class="hash-link" aria-label="Close에 대한 직접 링크" title="Close에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">일부 Close Callback 들이 실행되는 단계</li>
<li class=""><code>socket.close</code> 등</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="연습-문제">연습 문제<a href="https://clud.me/blog/event-loop#%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C" class="hash-link" aria-label="연습 문제에 대한 직접 링크" title="연습 문제에 대한 직접 링크" translate="no">​</a></h3>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'timeout'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">setImmediate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'immediate'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>출력 결과는?</p>
<ol>
<li class=""><code>timeout</code> → <code>immediate</code></li>
<li class=""><code>immediate</code> → <code>timeout</code></li>
<li class=""><strong>알 수 없다.</strong></li>
</ol>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> fs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'fs'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">fs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">readFile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">__filename</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'timeout'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">setImmediate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'immediate'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>출력 결과는?</p>
<ol>
<li class=""><code>timeout</code> → <code>immediate</code></li>
<li class=""><strong><code>immediate</code></strong> <strong>→</strong> <strong><code>timeout</code></strong></li>
<li class="">알 수 없다.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="레퍼런스">레퍼런스<a href="https://clud.me/blog/event-loop#%EB%A0%88%ED%8D%BC%EB%9F%B0%EC%8A%A4" class="hash-link" aria-label="레퍼런스에 대한 직접 링크" title="레퍼런스에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif" target="_blank" rel="noopener noreferrer" class="">✨♻️ JavaScript Visualized: Event Loop</a></li>
<li class=""><a href="https://nodejs.org/ko/docs/guides/event-loop-timers-and-nexttick/" target="_blank" rel="noopener noreferrer" class="">Node.js 이벤트 루프, 타이머, `process.nextTick()` | Node.js</a></li>
<li class=""><a href="http://egloos.zum.com/sweeper/v/3195982" target="_blank" rel="noopener noreferrer" class="">[Node.js] Understanding the Node.js Event Loop (번역) #2</a></li>
<li class=""><a href="https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/" target="_blank" rel="noopener noreferrer" class="">Tasks, microtasks, queues and schedules</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="JavaScript" term="JavaScript"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[혼자 생각해 본 개발 문화]]></title>
        <id>https://clud.me/blog/thoughts-on-dev-culture</id>
        <link href="https://clud.me/blog/thoughts-on-dev-culture"/>
        <updated>2020-03-12T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[여러 개발팀의 문화를 보면서 항상 좋은 문화와 방법에 대해 생각해왔다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="혼자-생각해-본-개발-문화">혼자 생각해 본 개발 문화<a href="https://clud.me/blog/thoughts-on-dev-culture#%ED%98%BC%EC%9E%90-%EC%83%9D%EA%B0%81%ED%95%B4-%EB%B3%B8-%EA%B0%9C%EB%B0%9C-%EB%AC%B8%ED%99%94" class="hash-link" aria-label="혼자 생각해 본 개발 문화에 대한 직접 링크" title="혼자 생각해 본 개발 문화에 대한 직접 링크" translate="no">​</a></h2>
<p>여러 개발팀의 문화를 보면서 항상 좋은 문화와 방법에 대해 생각해왔다.</p>
<p>어떤 좋은 방법이 있더라도 결국 팀 안에서 상황에 맞춰서 바꿔 적용하는 게 정답일 거 같다는 생각이 든다.</p>
<p>내가 생각했을 때 개발팀에 있으면 좋겠다고 생각하는 문화, 방법들을 정리해 보려고 한다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="코드-리뷰">코드 리뷰<a href="https://clud.me/blog/thoughts-on-dev-culture#%EC%BD%94%EB%93%9C-%EB%A6%AC%EB%B7%B0" class="hash-link" aria-label="코드 리뷰에 대한 직접 링크" title="코드 리뷰에 대한 직접 링크" translate="no">​</a></h3>
<p>코드 리뷰를 했을 때 얻을 수 있는 이점은 <strong>문제가 생길만한 부분의 코드를 먼저 발견</strong>, <strong>코드 스타일 ( Convention ) 준수</strong>, <strong>중복 코드를 방지</strong> 등이 있다.</p>
<p>개발하다 보면 본인이 발견하지 못한 실수를 다른 사람이 먼저 발견하여 고칠 수 있으며, 정해진 코드 스타일을 지킴으로써 일관된 스타일의 코드를 작성할 수 있다.</p>
<p>코드 리뷰가 좋다는 말은 항상 들어서 알고는 있었으나 구체적으로 어떤 부분이 좋은지 모르고 있었는데, 실제로 코드 리뷰를 해보니 상당한 효과를 많이 봤다.</p>
<p>최근에 직접 겪었던 사례로 기존 서비스에서 "A 기능"을 조금 수정하고 코드 리뷰 요청을 했는데 리뷰 중 전혀 상관없어 보였던 "B 기능"에 문제가 생길 수 있지 않냐는 코멘트를 듣고 확인해보니 실제로 영향을 받고 있었다.</p>
<p>내부 로직이 복잡해서 정확하게 확인하지 못했던 부분인데, 리뷰를 통해서 문제가 있을 수 있다는 것을 알게 되고 다시 수정해서 문제없이 배포할 수 있었다.</p>
<p><strong>코드 리뷰는 할 수 있다면 하는게 좋다.</strong></p>
<ul>
<li class=""><a href="https://tech.kakao.com/2016/02/04/code-review/" target="_blank" rel="noopener noreferrer" class="">카카오스토리 팀의 코드 리뷰 도입 사례 - 코드 리뷰, 어디까지 해봤니?</a></li>
<li class=""><a href="https://blog.logi-spot.com/%EC%BD%94%EB%93%9C%EB%A6%AC%EB%B7%B0%EC%9D%98-%EC%A7%84%EC%A7%9C-%EB%AA%A9%EC%A0%81%EC%9D%80-%EB%94%B0%EB%A1%9C%EC%9E%88%EB%8B%A4/" target="_blank" rel="noopener noreferrer" class="">코드리뷰의 진짜 목적은 따로있다</a></li>
<li class=""><a href="https://velog.io/@zetlos/%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C-%EB%A6%AC%EB%B7%B0%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A7%A7%EC%9D%80-%EC%9D%B4%EC%95%BC%EA%B8%B0" target="_blank" rel="noopener noreferrer" class="">소스코드 리뷰에 대한 짧은 이야기</a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="iac--infrastructure-as-code-">IaC ( Infrastructure as Code )<a href="https://clud.me/blog/thoughts-on-dev-culture#iac--infrastructure-as-code-" class="hash-link" aria-label="IaC ( Infrastructure as Code )에 대한 직접 링크" title="IaC ( Infrastructure as Code )에 대한 직접 링크" translate="no">​</a></h3>
<p>클라우드 환경에서 리소스를 생성하고 삭제하는 건 너무나 간단하다. 클릭 한번, CLI 명령어 한 번에 리소스가 생성되고 삭제되기 때문이다.</p>
<p>리소스의 생성/삭제가 간편하기 때문에 수동으로 리소스를 필요할 때 마다 바로바로 만들어서 사용했다.</p>
<p>이렇게 인프라를 관리해도 1~2명의 인원이 관리할 때 어려움이 없었다.</p>
<p>하지만 인원이 늘어나고 서비스 규모가 커짐에 따라 불필요한 리소스가 생성되기도 하고, 필요한 리소스를 삭제하는 실수가 발생하기도 했다.</p>
<p>더 큰 문제는 시간이 지나면서 어떤 목적과 의도로 만들었는지에 대한 히스토리가 전달되지 않았고, 이로 인해 인프라 관리가 정말 어려워졌다.</p>
<p>이런 문제점들을 해결하기 위해 IAC ( Infrastructure as Code ) 가 등장했다.</p>
<p>유연성이 떨어지는 스크립트가 사람이 직접 리소스를 생성하는 대신, 코드를 이용해 시스템을 자동으로 구축, 관리, 프로비저닝을 하게 되었다.</p>
<p>코드로 관리하기 시작하면서 빠르고 정확하게 관리할 수 있으며, 동일한 환경을 구성할 때도 정말 간단해진다.</p>
<p>대표적으로는 Terraform, AWS CDK 등이 있다.</p>
<p><strong>IaC 는 더이상 선택이 아니라 필수다.</strong></p>
<ul>
<li class=""><a href="http://www.itworld.co.kr/news/118469" target="_blank" rel="noopener noreferrer" class="">"클라우드 시대 서버 관리에 필수" 코드형 인프라의 이해</a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="문서화">문서화<a href="https://clud.me/blog/thoughts-on-dev-culture#%EB%AC%B8%EC%84%9C%ED%99%94" class="hash-link" aria-label="문서화에 대한 직접 링크" title="문서화에 대한 직접 링크" translate="no">​</a></h3>
<p>개발하다 보면 무언가 정리하기 위해 문서화의 필요성을 느낄 때가 있다. 특히 개발자끼리 의사소통을 할 때 문서화의 필요성을 많이 느낀다.</p>
<p>문서화는 코드로만 표현하기 어려운 정보들을 보충하는 것이다. 코드는 텍스트로만 표현하기 때문에 이해가 쉽게 안 될 경우가 많다.</p>
<p>이런 경우 UML, flowchart 등의 시각적 자료들은 코드의 이해를 돕는 게 매우 효과적이다.</p>
<p>최근에 많이 적용되고 있는 MSA 에서 여러 서비스를 통신해서 기능을 만드는 경우에도 문서화를 잘해두면 이해하기가 훨씬 수월하다.</p>
<p>문서는 상부에 보고를 위해 만드는 게 아니라 의사소통을 위해 만드는 게 더 맞지 않냐는 생각이 든다.</p>
<p>가장 중요한 건 문서를 만들었으면 지속해서 관리를 해줘야 한다는 점이다.</p>
<p>오히려 만들어놓고 관리 안된 문서는 없는것보다 못하다.</p>
<p><strong>문서화 작업도 업무의 일환으로 생각하고 일정 잡을 때 충분히 고려되어야 한다.</strong></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="회고">회고<a href="https://clud.me/blog/thoughts-on-dev-culture#%ED%9A%8C%EA%B3%A0" class="hash-link" aria-label="회고에 대한 직접 링크" title="회고에 대한 직접 링크" translate="no">​</a></h3>
<p>스프린트 회고, 스쿼드 회고, TF 회고 등 여러 회고를 참석해보면서 느낀 점은 회고를 통해 내 생각을 정리하고 공유할 수 있는 시간이 만들어진다는 것이다.</p>
<p>회고라는 시간을 갖지 않고도 더 자주 공유하고 더 자주 대화를 하는 게 가장 좋은 방법이겠지만, 현실에서는 쉽지는 않다고 생각한다.</p>
<p>아쉬운 점, 잘한 점, 개선할만한 내용을 찾아내고 Action Plan을 도출해서 앞으로 더욱 팀이 성장할 수 있는 방향을 찾는 게 팀의 성장에도 굉장히 도움이 된다고 생각한다.</p>
<ul>
<li class=""><a href="https://spoqa.github.io/2018/08/29/retrospect.html" target="_blank" rel="noopener noreferrer" class="">스포카에서는 회고를 어떻게 할까?</a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="신규-입사자-적응-기간">신규 입사자 적응 기간<a href="https://clud.me/blog/thoughts-on-dev-culture#%EC%8B%A0%EA%B7%9C-%EC%9E%85%EC%82%AC%EC%9E%90-%EC%A0%81%EC%9D%91-%EA%B8%B0%EA%B0%84" class="hash-link" aria-label="신규 입사자 적응 기간에 대한 직접 링크" title="신규 입사자 적응 기간에 대한 직접 링크" translate="no">​</a></h3>
<p>개발자가 팀에 적응하는데 까지는 짧게 1달 ~ 길게는 6달 정도의 시간이 필요하다고 한다.</p>
<p>이 시간을 최소화하고, 빠른 업무 적응을 위해서는 신규 입사자가 기존 구성원들과 함께 제품, 시스템에 대해 이해도를 쌓아가는 시간이 필요하다. ( e.g. 스포카의 부트캠프 )</p>
<p>서비스를 사용하면서 문제점, 버그를 찾아 이슈로 만들고 스스로 해결해나가는 과정에서 서비스에 대한 이해도를 높일 수 있을 뿐만 아니라 코드를 직접 수정하다보니 자연스럽게 업무에 대해 적응이 된다.</p>
<p><strong>신규 입사자 적응 기간은 개인의 적응 뿐만 아니라 더 나아가 팀의 성장을 위한 투자라고 생각한다.</strong></p>
<ul>
<li class=""><a href="https://spoqa.github.io/2019/10/22/bootcamp-review.html" target="_blank" rel="noopener noreferrer" class="">스포카에서 신입 개발자가 적응하는 법: 부트캠프 후기</a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="프로페셔널">프로페셔널<a href="https://clud.me/blog/thoughts-on-dev-culture#%ED%94%84%EB%A1%9C%ED%8E%98%EC%85%94%EB%84%90" class="hash-link" aria-label="프로페셔널에 대한 직접 링크" title="프로페셔널에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">각 분야의 전문가로서, 당연하다고 생각한것 들은 타협하지 말고 말할 수 있어야 한다.</li>
<li class="">(*) 업무에 대한 시간을 측정하고, 그 시간 안에 끝내야 한다.</li>
<li class="">내 일이 아니더라도, 주변 동료들이 어려움을 겪는다면 적극적으로 도와준다.</li>
<li class="">우리 모두가 프로라는 생각을 하는 것도 중요하다.</li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="아무소리" term="아무소리"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Go 표준 프로젝트 레이아웃 알아보기]]></title>
        <id>https://clud.me/blog/go-project-layout</id>
        <link href="https://clud.me/blog/go-project-layout"/>
        <updated>2020-03-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Go Lang 을 배우기 시작하면서 계속 프로젝트 구조에 대해 고민을 하고 있었으나, Go Lang 표준 프로젝트 레이아웃이 있어서 한번 둘러볼 겸 아주 간략하게 정리했다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="go-lang--표준-프로젝트-레이아웃">Go Lang  표준 프로젝트 레이아웃<a href="https://clud.me/blog/go-project-layout#go-lang--%ED%91%9C%EC%A4%80-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83" class="hash-link" aria-label="Go Lang  표준 프로젝트 레이아웃에 대한 직접 링크" title="Go Lang  표준 프로젝트 레이아웃에 대한 직접 링크" translate="no">​</a></h2>
<p>Go Lang 을 배우기 시작하면서 계속 프로젝트 구조에 대해 고민을 하고 있었으나, Go Lang 표준 프로젝트 레이아웃이 있어서 한번 둘러볼 겸 아주 간략하게 정리했다.</p>
<p>상세한 내용을 보고 싶으면 <code>golang-standards/project-layout</code> Repository 를 참고한다.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>정보</div><div class="admonitionContent_BuS1"><p><code>/src</code> 폴더는 사용하지 않는다.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="go-directories">Go Directories<a href="https://clud.me/blog/go-project-layout#go-directories" class="hash-link" aria-label="Go Directories에 대한 직접 링크" title="Go Directories에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="cmd">/cmd<a href="https://clud.me/blog/go-project-layout#cmd" class="hash-link" aria-label="/cmd에 대한 직접 링크" title="/cmd에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">메인 애플리케이션들을 넣어둔 폴더이다</li>
<li class="">각 애플리케이션의 디렉토리 이름은 실행하기 원하는 애플리케이션과 이름이 동일해야 한다 ( e.g. <code>/cmd/myapp</code> )</li>
<li class=""><code>/internal</code> 과 <code>/pkg</code> 디렉토리 에서 참조하여 호출하는 작은 <code>main</code> 함수를 두는게 일반적이다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="internal">/internal<a href="https://clud.me/blog/go-project-layout#internal" class="hash-link" aria-label="/internal에 대한 직접 링크" title="/internal에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">애플리케이션과 라이브러리의 내부 코드를 넣어둔 폴더이다</li>
<li class="">외부 애플리케이션이나 라이브러리는 이 폴더에 있는 코드를 참조할 수 없다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="pkg">/pkg<a href="https://clud.me/blog/go-project-layout#pkg" class="hash-link" aria-label="/pkg에 대한 직접 링크" title="/pkg에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">외부 애플리케이션에서 이 프로젝트에서 참조할 수 있는 코드들을 넣어둔 폴더이다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="vendor">/vendor<a href="https://clud.me/blog/go-project-layout#vendor" class="hash-link" aria-label="/vendor에 대한 직접 링크" title="/vendor에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">애플리케이션에 연관 있는 외부 라이브러리들을 수동으로 관리할 때 넣어둔 폴더이다</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="service-application-directories">Service Application Directories<a href="https://clud.me/blog/go-project-layout#service-application-directories" class="hash-link" aria-label="Service Application Directories에 대한 직접 링크" title="Service Application Directories에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="api">/api<a href="https://clud.me/blog/go-project-layout#api" class="hash-link" aria-label="/api에 대한 직접 링크" title="/api에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">OpenAPI, Swagger 스펙, JSON 스키마 파일, 프로토콜 정의 파일들을 넣어둔 폴더이다</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="web-application-directories">Web Application Directories<a href="https://clud.me/blog/go-project-layout#web-application-directories" class="hash-link" aria-label="Web Application Directories에 대한 직접 링크" title="Web Application Directories에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="web">/web<a href="https://clud.me/blog/go-project-layout#web" class="hash-link" aria-label="/web에 대한 직접 링크" title="/web에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">웹 애플리케이션 컴포넌트 들을 넣어둔 폴더이다
<ul>
<li class="">assets 파일들</li>
<li class="">Server Side Teampltes</li>
<li class="">SPA</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-application-directories">Common Application Directories<a href="https://clud.me/blog/go-project-layout#common-application-directories" class="hash-link" aria-label="Common Application Directories에 대한 직접 링크" title="Common Application Directories에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="configs">/configs<a href="https://clud.me/blog/go-project-layout#configs" class="hash-link" aria-label="/configs에 대한 직접 링크" title="/configs에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">설정 파일의 템플릿 혹은 기본 설정 들을 넣어둔 폴더이다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="init">/init<a href="https://clud.me/blog/go-project-layout#init" class="hash-link" aria-label="/init에 대한 직접 링크" title="/init에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">시스템( systemd, upsert, sysv ) 혹은 프로세스 ( runit, supervisord )설정 파일들을 넣어둔 폴더이다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="scripts">/scripts<a href="https://clud.me/blog/go-project-layout#scripts" class="hash-link" aria-label="/scripts에 대한 직접 링크" title="/scripts에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">다양한 빌드, 설치, 분석, 그 외 다른 행동을 하기 위한 스크립트들을 넣어둔 폴더다</li>
<li class="">이 폴더에 있는 스크립트들은 최상위 폴더에 있는 <code>Makefile</code> 을 작고 간단하게 만든다
<ul>
<li class="">e.g. <a href="https://github.com/hashicorp/terraform/blob/master/Makefile" target="_blank" rel="noopener noreferrer" class="">https://github.com/hashicorp/terraform/blob/master/Makefile</a></li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="build">/build<a href="https://clud.me/blog/go-project-layout#build" class="hash-link" aria-label="/build에 대한 직접 링크" title="/build에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">패키지 와 CI 설정 정보를 넣어둔 폴더이다.</li>
<li class="">클라우드 정보 ( AMI ), 컨테이너 ( Docker ), OS ( deb, rpm, pkg ) 패키지 설정 정보와 스크립트들은 <code>/build/package</code> 폴더에 넣는다</li>
<li class="">CI ( Travis, Circle, drone ) 설정 파일들은 <code>/build/ci</code> 폴더에 넣는다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="deployments">/deployments<a href="https://clud.me/blog/go-project-layout#deployments" class="hash-link" aria-label="/deployments에 대한 직접 링크" title="/deployments에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">IaaS, PasS, 시스템 또는 컨테이너 오케스트레이션 배포 설정 파일 또는 템플릿을 넣어두는 폴더이다. ( docker-compose, kubernetes, helm, mesos, terraform, bosh )</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="test">/test<a href="https://clud.me/blog/go-project-layout#test" class="hash-link" aria-label="/test에 대한 직접 링크" title="/test에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">추가 테스트 애플리케이션 또는 테스트 데이터를 넣어둔 폴더이다.</li>
<li class="">이 폴더는 자유롭게 구성한다</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="other-directories">Other Directories<a href="https://clud.me/blog/go-project-layout#other-directories" class="hash-link" aria-label="Other Directories에 대한 직접 링크" title="Other Directories에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="docs">/docs<a href="https://clud.me/blog/go-project-layout#docs" class="hash-link" aria-label="/docs에 대한 직접 링크" title="/docs에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">디자인과 사용자들의 문서를 넣어둔 폴더이다 (  <code>godoc</code> 으로 만든 문서들도 포함된다 )</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="tools">/tools<a href="https://clud.me/blog/go-project-layout#tools" class="hash-link" aria-label="/tools에 대한 직접 링크" title="/tools에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">이 프로젝트를 사용하기 위한 도구들을 넣어둔 폴더이다</li>
<li class="">이 폴더에 있는 도구들은  <code>/pkg</code> 와 <code>/internal</code> 폴더에 있는 코드를 참조할 수 있다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="examples">/examples<a href="https://clud.me/blog/go-project-layout#examples" class="hash-link" aria-label="/examples에 대한 직접 링크" title="/examples에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">애플리케이션 또는 공개 라이브러리의 예시들을 넣어둔 폴더이다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="third_party">/third_party<a href="https://clud.me/blog/go-project-layout#third_party" class="hash-link" aria-label="/third_party에 대한 직접 링크" title="/third_party에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">external helper tool, forked code, 3rd party utilities 들을 넣어둔 폴더이다
<ul>
<li class="">e.g. Swagger UI</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="githooks">/githooks<a href="https://clud.me/blog/go-project-layout#githooks" class="hash-link" aria-label="/githooks에 대한 직접 링크" title="/githooks에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Git hooks 설정 파일을 넣어둔 폴더이다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="assets">/assets<a href="https://clud.me/blog/go-project-layout#assets" class="hash-link" aria-label="/assets에 대한 직접 링크" title="/assets에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">저장소에서 Go Lang 을 위한 assets 들을 넣어둔 폴더이다
<ul>
<li class="">e.g. 이미지, 로고</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="website">/website<a href="https://clud.me/blog/go-project-layout#website" class="hash-link" aria-label="/website에 대한 직접 링크" title="/website에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Github Pages 를 사용하지 않을 때 프로젝트 웹 사이트 정보들을 넣어둔 폴더이다</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="참고">참고<a href="https://clud.me/blog/go-project-layout#%EC%B0%B8%EA%B3%A0" class="hash-link" aria-label="참고에 대한 직접 링크" title="참고에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/golang-standards/project-layout" target="_blank" rel="noopener noreferrer" class="">golang-standards/project-layout</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="Go" term="Go"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Notion Custom Domain 연결]]></title>
        <id>https://clud.me/blog/notion-custom-domain</id>
        <link href="https://clud.me/blog/notion-custom-domain"/>
        <updated>2020-02-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Notion 을 내 프로필 + 블로그로 사용하기 시작하면서 개인 도메인 연결이 필요하다고 생각했다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="notion-custom-domain-연결">Notion Custom Domain 연결<a href="https://clud.me/blog/notion-custom-domain#notion-custom-domain-%EC%97%B0%EA%B2%B0" class="hash-link" aria-label="Notion Custom Domain 연결에 대한 직접 링크" title="Notion Custom Domain 연결에 대한 직접 링크" translate="no">​</a></h2>
<p>Notion 을 내 프로필 + 블로그로 사용하기 시작하면서 개인 도메인 연결이 필요하다고 생각했다.</p>
<p>하지만 Notion 은 아직 개인 도메인 연결을 지원하지 않고 있기 때문에 ( <del>지원할 예정이라는데 언제...</del> ) 다른 방법을 찾아보다가 CloudFlare Worker 를 사용한 방법을 발견해서 바로 적용하기로 했다.</p>
<p>하지만 CloudFlare Worker Script 를 직접 넣고 하는 과정이 매우 번거로웠기 때문에 겸사겸사 최근에 사용해봤던 Terraform 으로 사용해보기로 결정했다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="순서">순서<a href="https://clud.me/blog/notion-custom-domain#%EC%88%9C%EC%84%9C" class="hash-link" aria-label="순서에 대한 직접 링크" title="순서에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-notion-을-공개-페이지로-공유한다">1. Notion 을 공개 페이지로 공유한다.<a href="https://clud.me/blog/notion-custom-domain#1-notion-%EC%9D%84-%EA%B3%B5%EA%B0%9C-%ED%8E%98%EC%9D%B4%EC%A7%80%EB%A1%9C-%EA%B3%B5%EC%9C%A0%ED%95%9C%EB%8B%A4" class="hash-link" aria-label="1. Notion 을 공개 페이지로 공유한다.에 대한 직접 링크" title="1. Notion 을 공개 페이지로 공유한다.에 대한 직접 링크" translate="no">​</a></h4>
<p><img decoding="async" loading="lazy" alt="Notion Custom Domain 연결" src="https://clud.me/assets/images/image-1-a82d6426e4e64fc220b2c6d6eaca3cc1.webp" width="884" height="578" class="img_ev3q"></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-terraform-프로젝트-다운로드">2. Terraform 프로젝트 다운로드<a href="https://clud.me/blog/notion-custom-domain#2-terraform-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C" class="hash-link" aria-label="2. Terraform 프로젝트 다운로드에 대한 직접 링크" title="2. Terraform 프로젝트 다운로드에 대한 직접 링크" translate="no">​</a></h4>
<p><code>notion-cloudflare-proxy</code> 프로젝트를 다운로드 받은 후  <a href="http://readme.md/" target="_blank" rel="noopener noreferrer" class=""><code>README.md</code></a> 에 적혀 있는 순서 대로 설치한다.</p>
<ul>
<li class=""><a href="https://github.com/claudeseo/notion-cloudflare-proxy" target="_blank" rel="noopener noreferrer" class="">ClaudeSeo/notion-cloudflare-proxy</a></li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-1-cloudflare_zone-부분에서-에러-발생-시">2-1. cloudflare_zone 부분에서 에러 발생 시<a href="https://clud.me/blog/notion-custom-domain#2-1-cloudflare_zone-%EB%B6%80%EB%B6%84%EC%97%90%EC%84%9C-%EC%97%90%EB%9F%AC-%EB%B0%9C%EC%83%9D-%EC%8B%9C" class="hash-link" aria-label="2-1. cloudflare_zone 부분에서 에러 발생 시에 대한 직접 링크" title="2-1. cloudflare_zone 부분에서 에러 발생 시에 대한 직접 링크" translate="no">​</a></h4>
<p>이미 CloudFlare Zone 에 등록된 경우 에러가 발생할 수 있다.</p>
<p>그런 경우 아래의 명령어를 통해 해결할 수 있다.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ terraform </span><span class="token function" style="color:#d73a49">import</span><span class="token plain"> cloudflare_zone.clud </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">ZONE_ID</span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p><img decoding="async" loading="lazy" alt="ZONE_ID 는 CloudFlare 우측 하단에서 확인할 수 있다." src="data:image/webp;base64,UklGRlojAABXRUJQVlA4WAoAAAAIAAAAoQMANwIAVlA4ILYiAADQygCdASqiAzgCAAAAJaW7jQBy8Dn/I5KepLDD/W8UCBzzlbuHnffSJ/pN9L6Kv1pcid8I/xP8Lf1r8Vf5P+GH7Nf4P25/BfiP5L+Fn9D/yf+E5e8SP4Z9LPkX9T/TH+lf5n/D/HX9A/A/9Wv7x7c+jb8Iv2d/u32BfiP8J/kP4gf0r/Yf4HlJQAfh/8L/pH9P/XH++f8P/XexX+c/gz7k+IB/CP4Z/Mf7B+rn9Z/5v0z/i/9H5INAH+H/yn+q/2T9ev8p/8/tQ/Vv7t/fv8T/h/8z/2/eP+Tf1r/A/3L9nP8Z/9fwE/hv8a/qH9j/xH+B/s//n/1P26+wT9u/Yf/UH70v3/T1Bk8abRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabRMabQ+yPg/l4MU6oR2K492DaMfMnjTaJjTaJjTaJjTaJjTaJjTaIrCZz5vT9tsgcT35TYE9T1blSS9PmTxptExptExptExptExptExptExpmXGLqED3MHOyXTtDiYL7aMfMnjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaJjTaIlJrXtwT18UUZBrVi+meOwRg0JiJKI2/DRJeKozcxVQvVzJ402iY02iY02iY02iY02iY02iY0yK9UuGj95XemlrdC842R0pJP1HPotrljiGnKUak8xzurlajrSKm0TGm0TGm0TGm0TGm0TGm0TGm0TGm0TGm0TGm0TGm0TGm0TGm0TGm0TGm0TGmu4bdcyqia4QgxJZx6Saq7Lbnz8IQYks49JNVdltz5+EIMSWcb0U5F96PmTxptExq15hnVu0bPdV9d5o6IpuKm3aNns1oSg8teoX+4MnjTaJjtI2vT5k8abRMabRMabR+tenzLz/OHlr0+ZQeZJFASU27Rs91X13mjoim4qbdoneraFkY+ZQilg8tenzJ1NMHLHwdwxiSzj0k1V2W3Pn4QgxJZx6Saq7Lbm78IQYks49EqYvlq8NExptExpqwOxLSHhVtGPmTxptExptExptExptExptExptExpsbPZAQKbagv19HyT5OTQPoLnUaSZbpOW5EpImC5WLR0eScgoLMLyU+Mq6wgV1cdV7Nmeh6U3xDFvf5k8abRMabRMabRMabRMabRMabRMPKmEtN3aF3E6tcZ7mV8vCxB/pllomNNomNNomNNomNNomNNomNNomM1CE9o2e6r67zR0RTcVNu0bPdV9d5o6IptsEjoTxptExptExptExptExptExptExptExptExptExptEw8qXc9aDxvraf5zRrdtvOPl5/VelWDcwWDy16fMnjTaJjTaJjTaJjTaJjTZ5dub5ULoIVEiY4OI+71EOH0TigJ4fqUZKoYN3y3qqObIwW/eafTLtLRXF2JzrMDu9QkwMBLX7/7DgyeNNomNNomNNomNNomNNomNa6Dr02XiceDm9b7mfdO836bRMabRMabRMabRMabRMabRMabRKqJMyXn4QgxJZx6Saq7Lbnz8IQYks49JNVdltz5+EIMSSwh9T5k8abRMR76GuFZKbdo2e6r67zR0RTcVNu0TQJ0CY02eDOD2/T5k8abRSQGDaMfMnjTaJjTaJjTlf20Y+0rBk8abRMaudaMfMnjTaJjTaJjTaKI0Y+ZQilg8tenzJ1NLfE8eUrvNHRFNxU27Rs91X13mjnhYQyPLXp9pWDJ402iY0OK1TUHpqYxJZx6Saq7Lbnz8IQYks49JNVdltz5+EIMSWcekj17+CxJjTaJjTZ1u+26meibzE8jNUAlWlxi5zNq7IfdsqluYMdJlR1iVWfOl+npIvxK2iIbRj5k8abRMabRMabRMabRMabRMZtRDdLDyuypsI8pn2VidURp57OOLrcFPxwq/X9/HDNihQQX0mDCHLtenzJ402iY02iY02iY02iY02iY02iY02iY02iY02iY02iY02iY02iY02iY02iIe5o6IpuKm3aNnuq+u80dEU3FTbtGz3Tc7qlPmTw8AAD+//7254AAAAAAAP35hnk6Qg1Mt/BkEBE1406TRg//HdBCa8NQSiT65H640Gn7tRYp7j141nW3kDB5eJWmngyY/WP02uPEJdcV2JF553MVAaSsjHCJtDzR2Y7Cd0p6g9uyVP/n5B8Dqaam5tahYp0mkayGtIPpFFarpksLlCKHjCfySY4y/+U2fs99ZdctjnNuf/P+nrEzSXyEu1ngbOe3DU19cQacPZPWn8pHWOhP/fqJT8y/lkrksPUDT4SHtIAPQbLc4Lq/gCTAOXB4BTJ8YZpmSI7lNWHP6HXA+m39iB+mTVoYLHVni5EcyjgHHT6BsVeA+OPc2PnGGfftiuF81oDG2SRvw507sMX0efcE8x26Ol98S9AKMJS3tKFSMrkICCbfPcoe2iFJ++nbgTvgBaZIcO1njEKc2f9tGD6Knn+d7pHfY7fa67ujMjJDb3AwPbTncyydMte24An4plS3HlkrXKmOz/APc64sl0YuVGxFIQo9sReSQh8LW1vUVQSd1xppp4H+0aSP1w9u/zz9YlnKjaUC3z+2f3Kp0Cd4p5T7XUt7fvmSgPC/jFl8wXV9d1VizxVGqg6hYlXA5aP1JUI03CKhfe2+vINfu6t/TTJtYCAtjH6rx9ftwwDqRtYSw5Sfjg3czrERQ/90Njarnmj5Rhe+sQ167XJCmgMXr5IFeAlMiD3baAeTksZqmXBfq16nJbr5udo5ry+ksvEldLG91j/385/N7hUZ4aU1Gn8wjtaKbtGVwJIABHpZky9NxlKQCF3WnzQal0ZzpkGDJKjXmVErEGXNXawWNkVHjQfhPu7vkuBLo0Q4B9ByXtxLdqB2JGL69QmR2x0n9JTeQreQKAKw/fRgM8jAt9dyfq1ujibU8bY7EA4AD+ybDsbJkW1zIFSgcQId8nc9I5xZJ4mFT03L94rZ+tUXXpQEWGQxTfBVJKAUX99ceXFI9xec4KLdjJq3l4DKzD/RhCgr44LAAAAAAAF3qBjk/9l0if1f0AUgzIIM/StOqhoZkJYEu76loXqd7lrrWDyQS8uJ4YzsgG5bHF9uo2XWvcYkyaGb98atzyYrsEytqV1n75iLN6IEB4shBqbPaX1h2T/9gUXGjFaMVk6wpSPt7A++2E5Umun3cAf2a5EvOvnur3SXx6LZjanuF49cRWpyJDBtyGgqG348CXXz4M4/t2DBt5JjFMIQK5HwQfVV5T2OhX7mA+cxQhrjH5QAlrfwPA1Lu1rwGFidm6r6okTW0wVhZynAgQ4GC3Mb1BeRaqyHZuyIFO8HzDdmbe5Q68QLmX/MdagK0KLduRR9PoHAaA3mUtItFD33VBmnf64LiqVaF2t4iG5FUTf0DeDWLkS5iHX4TBa9FJtVXcAn7cKueg9ulqhKaejKRVr/Ug6LRkUEgBF7K+YNe8xGJigPAwqzc8JLoN9/3hpeXjnBbdSzsOFKnJYo7bP3FrBSGbzhWD8fCffQthtuvAjggwGKNPuj5yFNfRk5lm+y97ZLzKrbDikNMtK+wfoXsW4QuIiCiBD94+kf0sJsWFmW7kwzdlB4z4LVBM+HN+iSCdY8P8PRvUqFvrQXygy53DV0pI4GVaqeF2pdSV8/VEFBpDV/9YPAV4oLsmaTKU8pe1Cr4zHQEhVBB4EETL+j4Yy0Yt/176F8xgF31DJChIq+klDMNhiZL0A2+djIJjU/Bxe3vmset+O15nfbsc/XLohy/kWtv+ve8oc6rW/asVM+UjO1ssAr5VovX2U/Y7pC4+5ZxgYTRqE9Lpn/H8lEEoc0eusgYvCr/6Osh/46dnmMJazQYzErQsNZYtNv2SGN0P/ev8+cWSXk7CMpAvkkj/n9yQR4+mJshdxt5Jk1FFzHINn9jiSslbaew43ISSacwIbqRedn5uENlBnODqf0cS06X0LcEhZqAmfK5EOuodyo+DOZyLKPrD8o2otQWN+BMmtHEOSIMR2ro8NhSjln4aDQ4+1Fa8i9ljuPJnFFnBZv3k4oLt/sFc56ID+PFQyO4h5X3XCQEMc47duSa00yA0StIXjOcrzATBLHQlaZSrCeQ69uVFwJX0zXMK+Ld+DbQbk3LDA2e/FcTaj6WHM2eU4c2IAoPFI+0FhJzhxEpwSs2x5+0lLyDCzWZWO5/2xDxT/sA9PR9IzuVoi/+pLyCzElhXlZ1WcrONP5JpthH5Ny5EVPTNAEUGXPqLIBmVoaOdsnt9NSIdyMk5v1HTrfWYxVeeOpByap2JPQxT7OT7hzb3i28WoOzWjukJHdryr5FP9fBYsferevy7GR84ms4auG2aaclDnhTcWinIa9YCAC4dT67Wq1F4bbpwD3WwJsNccwU/Cl9S1PKRXpKrASKhX5nkT33/tzbKvHbxzQ9i7bpq1qusZ0ju/hGD57qDWxr0AyFY9T2yDDfbw5+0DXvbixFv6OZkrwaPwB5oAb6dlsemFQozIMiXkNGuZHhK+durx95LjIBfNkfFzAUxQhHFZc/L0gQ7h6s4CwN/rlYbTsRzzCxqAH+ZWD+FaPcs8m7wbwnXGS868fJYYV64F4wJfKUmzN8PXTzhBRySBGCexWf7Qhgp0gu4uAjCBqZetT+GhyMfAk8Ceb9GEtm7JiSd+HNCgP6dcjEu6obOvP0E3YCk7tuzj3/ykAIa7sltP02g+QraD6GYb1LImfsHH2aLDwNQxxnNgD0uxAAAGpT4zHoN9bEsv6VjQssl/TUGyeHqfhu6hUO4EzzuzSQ16Sg3E8XylKMFghhi/m0DQIF2YEwlPpP7yxNJgu7z8YOUtMvnKxkR2VCuafk/4C8oJAgkfMVABReYGp243AucLfrm4Ype16B5kduAAAiP3/Cn9vVUfMf4Cairbm5Q90piyvMqmJQy0KDY8D7TW9uMOrT6+6bFs/LgXSWeSH3gBy4QSADygAqcYwUdGbMpfZB0+ZsoPv/CjOoNFr6c8E8JMkkj2hj88gvWbJ8PjTARJYbQEz7QABW/qKXdyhwLkqD3r6IV7MATYFQ/cnaov9pVVLGeTRaJmrJL5Y/DGWhiNd4yM/GCC2+Q7gTh6FGTRkexZTbqBGAKn0OHfc8KevjzktT/NoAC0bfuChDiLwsFf0xVGf2Qc4PvME860KSI/IpR/d6hY1AlH8JzC/24qigzdceKDNyzMtL/MIErDM3j6ux0cr+CNzrWjJiowERyqjB+aXfM3n0vS5GUV21nb1sEx4edwcFudUbnUcvfRkkKfZ5r2qNQEGiU+MWmQge0DJXi9HcOxsof/bvxRD4jSQyh1ndVg4RSodkZbbuN0QVeRrtRu47RD+T1fbz/WkU1Ou8pqArmDQK/p9CR+2fiMc/6j8woNWSATOfO0WPhZJKVBNznC8LorUBOX6iQzxGidIeeH7Cbb2Lo8BcF5oeE6xC6bt98ds4pXCRirXxCfBkNku0tH1d4+HeOGQn8PLNzpWxzhRfjSnnSDcSJhO1Iv8u3zsfGFSJTB9ju+pHXsEK5wpAOaKeBiaK0EKZq/wgJbgWUrRU3f04No0hcU3DL06nHtof54q1zwm1q8Q7Y2kqW3GTLSaMMGdF8PNL7Cp2JVmF+8Guz7gDOgKID9eF7A9v33f+zl3RxGaJkv1htoVBjUTib8dlgiu+XuOo5L78JJj+Hgex+oDLloA+8DEstKQOBnSMiIFCbV2FSYqML0uFIC4HGCxS8ZOSE+Iosdk1sZMp9r1VE73TX8oH9m30dxNU6uqeGSpmL+sR7UP7aJikiitBjuuo+JK94J7Re5/KE94+hhy42VoPx8OJU8Gp4YQMq0XItLBT8LNCWcb8DhPXaktfsRwRwNjp3S9J2A2Uuw4HQ1ZLW59TKfrxmu/MSDZRgMRtpl8ucoDzd2ExlRpcmIKzwoTJuc/12Qg4rsBfX6lV3sP/o8DQVIaOUPxOaIXHyRWpy5VWVU9E0lUdV8Hm7QADpQXTvvnkG1+xiOnZg/9akcw+vF8QXmDPBA3toqK503G+eqVlQo47IXs5IyZwAYX5sSMSv9OQk8FLqUSh09A7h4wyPnQmrmoxPETE/YwsOpGFoPUUY8tcR13viaCfeWU4eJ2TUNKfLRjR0DdbLjfK7Vnae+tO6UDOdFGGSXjd5kLDQdk44t3FBcRgYJzONyBapTKz3DmIR3JUVdMC/rwWB2Nzwi4pfSemIKmqNkhbzLZ1P7LngiG4c/7/kZl2FBuRMRozSjJ8RV+kli3QJrgqIeYEBqm7srYhSUBGE5w9UrYShTftHpphk/HjQsDf5xnhcV58b/3yeoyTGNdH5e8g+s0jOHtAQDJ/csvcKpL4o3uE+ti32erSaA3WoNk5+peWTj/G/dIOuBHZRLw3Z9c81H7jg3hBZZI10mWu7IDZRQ3bDbVL7N/s4okq4bmbFwd7teXTHxgrLM0PyEhtK1vaFuObvK1R/UlIpO1ltu+R2PwVne36DTLScVaWoxxzAnG84MmW+i4qMb14h5Fgu6sw3eV4f2w4QOHjb4dpQVZ+jz87/9zkpH9XxeDpXbY9QtDLCdtFfFfmswYJTSaKThfk6D1FNqnMRPNJvO3Tyvdj/iQzyYjnHwEl1+Ff9KIa5pCOzu8cbK4bRDGg2xL168mBepCDQhIMtMqKDnJrI1WZ5x6izE7vEK2BeEz3w9kWk4WtSdRCBvkoEOEuKf4eMSAHbPqCTqQMZksUdd3mIV3vaC77aGHsHk3yctiJC3kzHAmYhp+MRZHqINrsg53wBr1WDWjeU3CjCNg94oHA1zOfI/H+0rk2TZnk/WU4EDFQv/MjdTrL3C2qj4D/nsCZ0YWioy3P29nIfSWsAStdgY12lA9AJ/P4AFppGAKBP0NcSmBhuPQCvArLrtopkALAIYjjfDrARY9BxwBoLjrLoNl85ili6H38kIl0s4iHX9nne8KeFFMAwcL37LUWwwWIi+LujltK/FrzZTXGUgpA2Uoa0wNpl7juUOxpswc7hfmCj3CLhVcKDMZRbq06HMkGEA2irISXaG3UgBIM1jnPoXOgf4PisAaAwo+4QCNu97yh0UAAAAKz3bLARw/7gdC2mBe4zeD/snw1B1e1eXO0T+A8Nor81jtuvX96WFmXyYM0u4JKV0nprMNikpAiqWycDb66rT7eMXzGOUBUFX0VfT7XfyGylrqbqJ2UzT1TygDwvI5u1jyGYtMPrGteaB5G0I+7/qJ/xC2gHsVBQYKqGyh4xai35teJCYjjfETqdP7wc2Yf5dhgIVs3+5dDSlznOKMFvAquZv2fMtyfnMcE7ugMmrYZ76p3yIZ3Czw2sJNhl5YNGK2Uw+NywXcqg67jqpefQNOPjL86nCJLjYAGcE3lQQnb3lv+uJOZrHsWKfflcQZQVlk4S+vy57vlNhTkrYJrdVoHhfvNIFSkx2gQ7JYfdQ8HsPZ+BNzo/grzj3MXOPW0wPZayb9rd8k1YnoVXFBiehI8d9EiT+QlwgNm/PMPWQlCn6oLXMl3VJQ8vDgNfjJW5ItjP9eZTOdJAzQWBPddPOGFKKhrqDO77/LijAFWYIdsQ5FsYXKgtIwzx7i3RnhIQP6emIrGfFFlAvz6D+D57hor0WbFjmbuE0922J8sJoxXHLgr/GzjUYzBW+GP9AMZnIcKUQ/+L9R+CKiFKscxR1DiLlO77u1u5xTY/sWnkX7qnJnxu7fth5C5ez2ZBRr7Htsu246d4dbBbaBmX455aVUXxbd3+3ZG0iUVTsZn+XBTDD/FFkIrp6SRl2++v6UCjpOgWMOYRW/TKeE5TNEIWTICzylnd4u750dFbARyFoJHzeJa/aKOrg3O0OvR4XSWmyJBKpiei9Fz/5pwaNY5UNahoxacrfgBy2Y+ooDAZAqLDbMa6WDNWg3Eb40PYds5vR7g8ho0UI44hVpB4jsiWG2CVdIyFtSP6fe4sxCBQ9ep1ZBcffbvWk/MZwVxWPGob5cLHI5lmybBp9FcSWwQsIbQGa2ywsfcqY6r0I2kXHqDDGOU5hgSxPsgQotfNfZPcxyHmjmfvlFJLBMdeMbz/VcpUqOKyojqSoAPjd7lS3Tp+903YuDNUc/Q45K+E+V1Jycco1yTCbyp3ncHp9M2jpUJUgFMFyZIWtvyvTLbGpBhQHgbgbtoIYU6mrvnPw/qNJK5BCJt3WuR7Dx3D2lpqmJPz1c0LAH0UWzzj8MQxWLozu5YjdsLE95TuwUdV8a8+3wa3z77F9GNnD6RbjiWAAR/951KfH2lJ32gC26osMAQvT9/LpOWNYh/D+/VxM9vzw6yN3X4u+zW4GV9ySGwNY0c4QrgjsioZ1Udm/5syrFAkUwmzhvUXr4NDEG1oZwR91LwoyRF+imQVRm2HKRSR/LYgaoukAidGX/2Mq6FTr3WtwjB1z83ClgtuZ7H0+uNao+yh+PezYq/0EHZbPQh+1ImkvBfoUDRcm22CquHRzftDrdx8rbcHgPDaudJzicEKUGiBUSMKmXMHJmEg8ZzK+C0frdGLcjAgDZUGwCT/xSNS/Or8ToFNzKQd0p4bruqxiypHqa9tTtHDLqwPVWvNMQv++i/QhMfOSFARZ8usnnMThXZNpaj8N0pqhfaplKmFyg/T4V9C2otLVLiNAxdsLlONl1nF3S6iGIV41SLevuTVyQqroOuTcXc1sJHegVaGhHyJAL/MP5vRYKlvCsTanLi4pPBYzYwE/hz1/POjG+KyRmieyIWVPMML5PyvrWbIMA6JnodE9HX+EJqEpW+1K9TYz7U5uAnhk5/w2aRXqdIqdD19imaQlYMqIg9JLQMy7arAgwJxKm3TJRg3GDcdl5AAz6v9JWs25biZizBAQzSHzWDi0+xoQwPtctc1f4o7Jfga1QK11S+3+6WeSq5vusKg2BJ3fNdYu0K1KRlvRKxyqEXY+m/6azDINjjoPyL9y4tixf3fq/AK5/aiyrUTRv/QV4AxlmvC18EfyZx2N0tM3iotw+N0gHPgzZEH2MhNlWjG2l4U1rVOHkK37LuwddyoWFZkxGTBBcl4InFTCXfPU2nGE2/NRKKYjF2KcWXdoxgc51tyVV0JJj4c5YGOWXfwnPe5l5vq9mGkbhbNh7Dk1H2AL4g1SAJaVmVecBbXp07JkFPIzwbJWTC1zk694aR5jsG2w6dqTet3WdKzswrObdGhp2I+U5A82OQPh9Ys2MuYBgM2vFCqhv7ZtxfWAP5TuJ45btnXUoawDd4ZkC7+/QE5DfEWPydiEWrlX5Ve96Hhkp1bGZ2xd9KtprNQIO9hhD5drfm3iQNkYk9UTcjTq0fReOIuABaqpMTaEkIOAg5TfQ8/0R4oFXvTAaX3yxsQ/yWqFfD6/AbdzqPmZXu380Xl8sM6cee25EBTyuzNT9awkVaZzIsWsGqIh7cN/3AJE1tpm8Bf0ABX7FNlvG6rP2qJ/Xo9h8UkeRDWIBTDcAqcYwUyNJOEZR0CQKXAZk2FDT4o2ON6a6jL4wofdAfFSs1h+AvKCQIJHzFQAAspRPQ7AyZYz9X0V8GiE3yZ4Mw9PdGnZD4FQRBByvaCoeQAAAQR4mjSStXu3/9/wp/b1VHzH+AUEVbc3KHulMWV5m5+gSa2inlfWvwlNCCj4t2n3ferQw6s+s3g9QYFTjGCqRSgT541xE2kiVMWu0xPpyZycwmWz73mqWoqADL5Ny8HuII1RpUG11tb0anprmVH3EHlRGc4C1fi30AcmvMi18S6bekO7LR0IrV7/pE7HuuQKfWHx/5KDYNWpWjOd+HJupYm/OyIp1YV7+y7JJD6ze7JBcoSs+J/yt3w2zCD9khzqB0KNRa2gg8pYYwSIEfqkcNDbdCDioFkNSM+etanw4UhGawwgRypY4AAgXf4V1qi8AQ2R7M6uE5mWl44cmYpEspW3SX8B4LhfH2tinId8MwTIy+0yLUZT/+I90pgaYAwnDMyTeQ6NTS31z6/CeGsOuCVHenFlnb1LMbae8YTag82kNlNZnAbaT7/BtAfzYev//5QjMUNxlr+RRqxSwl9CcgwI2WBhD4XUGhi86NpeKXx8nR2KigHwEOxhZ865/VK+GOso7IOOoo/ex1pUqmsIoMgI4DdgStmKKWlI1kaOw5YG3a8rJnU2nlzhaeDOZdxsHkWcnvUJB088x8Qwt1ibkKn8M9DXcob3R/XHz07cNRR3HkUErH8onrIeDqXny2XtF13y6pmex8O1r1QhFuGXbI/L4BE8S+ijvMoRJpko6nPKciZjHBOhrkkD4gZoWzixbNyGxRUz2NCvC+ya0sBkdsD4NH9qZ+1hCkenht11nwSQK/RoLmrolmt53ej/jSHkgWW0Mhyzg6OGChmRFkK14dV4dbwoUHmbUX/LUhvbnMMYmc1iV+RiQIh7Ze8E+v2mb6sy5PGR7Oc4wiRay+ro+6b6XbkAQPGoiJ8TC2xE9PwCtWfXcDF/nIaak9Cs36IGLae+3weDxtrOsL7SFzzO3/2eT3mHFGQbjVBr3u0DB3B1tQ0J2JyaiicZg03lPPkXeg/CXY+JWkqR7ybiWq4VdOTb/RgSikQdiKj/F+HKwJ92XPXCI6slTGnSkeTm8B0fK7cFMTHS249b3xr+nW2SAcGAtl1xhk8ef38dVAqMHhWF1qyomyyTqssPKft7AIoDug/QzbGa3KJbh+X7UvVQ9UKCkgYv4Bcxa5DBPfMOgSdvOTIrSMNnIgZ9qszoG09Y4nSLAU+p1JYIK0EukohPGxv7yfy6gdsq9/puYHO5Cg+eV05NANOf/y9n+Llaf3tiAwQ5M2CuulxaV35JnDLCGt2BQGjigXw+MVWs18MBQOqH+wXcbqyPu7J5E2CyD6tcEejJefMk8NDAvAc6MLG3GFSM1XRQKEhN0erfJ1cbADbFrZSvqZipI+0T3E5Czb3V266HKaedM+trmmavoHGcfGJw7op2VhWe+bMbc1H3EV3Y0UyVSzRpRNKMG0m3NBJeKOwV/Pndu/R4ulFc8nYTUkYFNIKQL+BA4yRnQQWBUwq7DQTR5nZMLHEq23YjTniSlANZ2RUMYkyeKjqtQ8am+6lT1q/5En2++A8chwLq3a8Y531Uy9Rq5mieQEF4rZCDSOz1wLVndWpHa9Mfl03R3ac6+IlItlNm9dEY9Nnfult4XI4jVfkfkPihZphUuTBFSiLH+O0KAza2mw+Ov1j2MtGlrGBzBYTVjsplQjPMR7wNC/yYOxZIflBe54Ao08XylbgR2ipxD2SWX63fao2uvp/BihOeC2BmB75AwXeBluR5AiVkpzb1LUcX0UPrfV6prbr7ArpyEzCThXHsPFyv0DXG/94f3KAX5w6tnlmb4PI9kOgRJ1js/aI0wzpLjmmkCRaUOdmYKzzONkePc0GVt3o4mnKRHocEZ5w9a+7LGO3I9AVuCKnV2op8NVYj/FKPOGOuL/2NTIGO5nH1ax+mE1M2cRCBxYDTMxI4XNGMWkLH8UUcZrIq/k8GT+vKiZgv9w9IA1osU/wgZWRHp9Sd0EjvsGTvr6iM/0jZ2Zldgqm9C9WL56aPKyCKBryJvA3w1ul6v1884t1ID4N+kvj7PMNiR+UY4SFpPG+OOkWLA7zlId4OnjcZ0WSDI6eshKbfxQNZXVjp4zLXxYZOV6q2SBinzxaQcY7+YAdP0/NL+mjdMq/k2QPWX2ueozoDsDym0xVxwKkdD7+VfaT6PWq+8EHX1oECOIsLzXp/7s2c+AAAAAA6tROPw5IvgDgAAAABFWElGfgAAAEV4aWYAAE1NACoAAAAIAAUBEgADAAAAAQABAAABGgAFAAAAAQAAAEoBGwAFAAAAAQAAAFIBKAADAAAAAQACAACHaQAEAAAAAQAAAFoAAAAAAAAASAAAAAEAAABIAAAAAQACoAIABAAAAAEAAAOioAMABAAAAAEAAAI4AAAAAA==" width="930" height="568" class="img_ev3q"></p>
<p><em>ZONE_ID 는 CloudFlare 우측 하단에서 확인할 수 있다.</em></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="todo">TODO<a href="https://clud.me/blog/notion-custom-domain#todo" class="hash-link" aria-label="TODO에 대한 직접 링크" title="TODO에 대한 직접 링크" translate="no">​</a></h2>
<p>편하게 사용할 수 있도록 수정하고 글을 이어서 작성해야지..</p>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="인프라" term="인프라"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[ElasticSearch 알아보기 (1)]]></title>
        <id>https://clud.me/blog/elasticsearch-1</id>
        <link href="https://clud.me/blog/elasticsearch-1"/>
        <updated>2020-02-03T00:00:00.000Z</updated>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="elasticsearch">ElasticSearch<a href="https://clud.me/blog/elasticsearch-1#elasticsearch" class="hash-link" aria-label="ElasticSearch에 대한 직접 링크" title="ElasticSearch에 대한 직접 링크" translate="no">​</a></h2>
<p>BLABLA</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="설치-방법--with-docker-">설치 방법 ( With Docker )<a href="https://clud.me/blog/elasticsearch-1#%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95--with-docker-" class="hash-link" aria-label="설치 방법 ( With Docker )에 대한 직접 링크" title="설치 방법 ( With Docker )에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="docker-compose">Docker Compose<a href="https://clud.me/blog/elasticsearch-1#docker-compose" class="hash-link" aria-label="Docker Compose에 대한 직접 링크" title="Docker Compose에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">version</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"3.7"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">services</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">elasticsearch</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> docker.elastic.co/elasticsearch/elasticsearch</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">7.5.1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">environment</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> xpack.security.enabled=false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> discovery.type=single</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">node</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ES_JAVA_OPTS=-Xms512m -Xmx512m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> 9200</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9200</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">ulimits</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">memlock</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token key atrule" style="color:#00a4db">soft</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">-1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token key atrule" style="color:#00a4db">hard</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">-1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">healthcheck</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">test</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> curl </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9200</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">interval</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 30s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">timeout</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 10s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">retries</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> elastic</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"esdata:/usr/share/elasticsearch/data"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">kibana</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> docker.elastic.co/kibana/kibana</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">7.5.1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> 5601</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">5601</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">healthcheck</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">test</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> curl </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">5601</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">interval</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 10s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">timeout</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 5s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">retries</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">depends_on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> elasticsearch</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> elastic</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">apm-server</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> docker.elastic.co/apm/apm</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">server</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">7.5.1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> 8200</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">8200</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">depends_on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> elasticsearch</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> kibana</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> elastic</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./apm</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">server.yml</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/usr/share/apm</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">server/apm</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">server.yml</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">metric-beat</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> docker.elastic.co/beats/metricbeat</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">7.5.1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">depends_on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> elasticsearch</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> kibana</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> elastic</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./metric</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">beat.yml</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/usr/share/metricbeat/metricbeat.yml</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">elastic</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">driver</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> bridge</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    esdata</span><span class="token punctuation" style="color:#393A34">:</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="apm-server">APM Server<a href="https://clud.me/blog/elasticsearch-1#apm-server" class="hash-link" aria-label="APM Server에 대한 직접 링크" title="APM Server에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apm-server</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"0.0.0.0:8200"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kibana</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"kibana:5601"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">output.elasticsearch</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">hosts</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"elasticsearch:9200"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">logging</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">to_files</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="metricbeat">MetricBeat<a href="https://clud.me/blog/elasticsearch-1#metricbeat" class="hash-link" aria-label="MetricBeat에 대한 직접 링크" title="MetricBeat에 대한 직접 링크" translate="no">​</a></h4>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">metricbeat.config.modules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">reload.enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">reload.period</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 10s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">setup.dashboards.enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">setup.kibana.host</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> kibana</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">5601</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">output.elasticsearch</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">hosts</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'elasticsearch:9200'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metricbeat.modules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">module</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> system</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">metricsets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> cpu</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> load</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> memory</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> network</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> process</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> process_summary</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> uptime</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> socket_summary</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">period</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 10s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">processes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'.*'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">cpu.metrics</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'percentages'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">core.metrics</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'percentages'</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="Elasticsearch" term="Elasticsearch"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Kubernetes]]></title>
        <id>https://clud.me/blog/kubernetes</id>
        <link href="https://clud.me/blog/kubernetes"/>
        <updated>2020-01-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[API Server, Scheduler, kubelet등 여러개의 컴포넌트로 이루어진 집합체]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="아키텍처">아키텍처<a href="https://clud.me/blog/kubernetes#%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98" class="hash-link" aria-label="아키텍처에 대한 직접 링크" title="아키텍처에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class="">API Server, Scheduler, kubelet등 여러개의 컴포넌트로 이루어진 집합체</li>
<li class="">사용자의 애플리케이션이나 데이터와 구별하여 Control Plane 이라고 부른다.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="마스터">마스터<a href="https://clud.me/blog/kubernetes#%EB%A7%88%EC%8A%A4%ED%84%B0" class="hash-link" aria-label="마스터에 대한 직접 링크" title="마스터에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">API Server</li>
<li class="">Scheduler</li>
<li class="">Controller Manager</li>
<li class="">etcd</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="노드">노드<a href="https://clud.me/blog/kubernetes#%EB%85%B8%EB%93%9C" class="hash-link" aria-label="노드에 대한 직접 링크" title="노드에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">kubelet</li>
<li class="">kube-proxy</li>
<li class="">컨테이너 런타임 ( 애플리케이션 )</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="add-on">Add-On<a href="https://clud.me/blog/kubernetes#add-on" class="hash-link" aria-label="Add-On에 대한 직접 링크" title="Add-On에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Dashboard</li>
<li class="">DNS</li>
<li class="">Ingress Controller</li>
<li class="">감시용 에이전트 ( Prometheus Node Exporter, Microsoft OMS Agent 등 )</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="설계-원칙">설계 원칙<a href="https://clud.me/blog/kubernetes#%EC%84%A4%EA%B3%84-%EC%9B%90%EC%B9%99" class="hash-link" aria-label="설계 원칙에 대한 직접 링크" title="설계 원칙에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p><a href="https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/architecture.md" target="_blank" rel="noopener noreferrer" class="">kubernetes/community</a></p>
</li>
<li class="">
<p><a href="https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/principles.md" target="_blank" rel="noopener noreferrer" class="">kubernetes/community</a></p>
</li>
<li class="">
<p><code>API Server</code> 만이 <code>etcd</code> 에 접근할 수 있다</p>
</li>
<li class="">
<p>부분적인 서버 장애가 클러스터 전체의 다운으로 이어지지 않도록 해야한다.</p>
</li>
<li class="">
<p>각 컴포넌트에 대한 지시를 잃어버려도 최근의 지시를 바탕으로 처리를 계속할 수 있도록 한다.</p>
</li>
<li class="">
<p>각 컴포넌트는 관련된 설정이나 상태를 메모리에 저장하지만 영구화는 <code>API Server</code> 를 통해 <code>etcd</code> 에 한다.</p>
</li>
<li class="">
<p>사용자나 다른 컴포넌트가 오브젝트를 변화시킨 것을 감지할 수 있도록 컴포넌트는 <code>API Server</code> 를 워치한다.</p>
</li>
<li class="">
<p><code>API Server</code> 에서 폴링하는 것이 아니라 각 컴포넌트가 자율적으로 워치한다.</p>
</li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="Kubernetes" term="Kubernetes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AWS Community Day - re:Invent 특집]]></title>
        <id>https://clud.me/blog/aws-community-day-reinvent</id>
        <link href="https://clud.me/blog/aws-community-day-reinvent"/>
        <updated>2020-01-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[시작 일시: 2020년 1월 21일 13시 00분]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="일정">일정<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%9D%BC%EC%A0%95" class="hash-link" aria-label="일정에 대한 직접 링크" title="일정에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class="">시작 일시: 2020년 1월 21일 13시 00분</li>
<li class="">종료 일시: 2020년 1월 21일 17시 30분</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="키노트">키노트<a href="https://clud.me/blog/aws-community-day-reinvent#%ED%82%A4%EB%85%B8%ED%8A%B8" class="hash-link" aria-label="키노트에 대한 직접 링크" title="키노트에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="신규-출시-서비스-및-기능-알아보기">신규 출시 서비스 및 기능 알아보기<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%8B%A0%EA%B7%9C-%EC%B6%9C%EC%8B%9C-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%B0%8F-%EA%B8%B0%EB%8A%A5-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0" class="hash-link" aria-label="신규 출시 서비스 및 기능 알아보기에 대한 직접 링크" title="신규 출시 서비스 및 기능 알아보기에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">AWS Graviton2 Processor
<ul>
<li class="">클라우드 기반 최초의 ARM 기반 프로세서</li>
<li class="">AWS 설계한 16mm 실리콘으로 64비트 ARM Neoverse 코어에 구축</li>
<li class="">최대 16개의 vCPU, 10Gbps</li>
<li class="">최대 40% 향상된 가격 대비 성능 제공</li>
<li class="">인스턴스 타입
<ul>
<li class="">M6g ( Preview )</li>
<li class="">C6g, R6g ( 2020년 Comming Soon )</li>
</ul>
</li>
</ul>
</li>
<li class="">AQUA ( Advanced Query Accelerator ) for Amazon Redshift
<ul>
<li class="">새로운 하드웨어 기반 가속 캐시를 통해 비용 증가 없이 타 클라우드 데이터 웨어하우스 보다 10배 빠르게 질의 실행</li>
<li class="">Amazon Redshift Update</li>
<li class="">RA3 Instance
<ul>
<li class="">기존 클라우드 기반 3배 성능 제공</li>
<li class="">비슷한 가격의 DS2 인스턴스로서 2배의 성능과 2배의 스토리지</li>
</ul>
</li>
<li class="">Amazon Athena Federated Query &amp; PartiQL
<ul>
<li class="">lambda 를 Connector 를 통해 다양한 데이터 베이스 솔루션과 연계하여 Query 할 수 있는 기능</li>
<li class="">RDS, Aurora, S3 통합 SQL 질의 가능</li>
<li class="">Apache Parquest 기반 S3 데이터 레이크 내보기를 통한 새로운 통찰력 제공</li>
<li class="">PartiQL
<ul>
<li class="">RDB 뿐만 아니라 다른 데이터 베이스에서도 쿼리를 할 수 있도록 만드는 표준 쿼리</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="">AWS Outposts
<ul>
<li class="">AWS 인프라 및 주요 서비스, API 및 개발 도구를 고객 온-프레미스로 확장하는 완전 관리횽 서비스로서 기존 클라우드 애플리케이션을 낮은 대기 시간과 일관된 배포 제공</li>
<li class="">AWS 리전 데이터 센터와 동일한 설계 인프라르 고객 시설에 제공</li>
<li class="">AWS 리전 내부와 마찬가지로 AWS 에서 전체 관리, 모니터링 및 운영</li>
<li class="">동일한 API 및 도구를 제공하는 클라우드 단일 운영</li>
<li class="">온-프레미스 및 클라우드 환경에서 하이브리도 사용 가능</li>
<li class="">서울 리전에 출시</li>
</ul>
</li>
<li class="">AWS Wavelength
<ul>
<li class="">5G 네트워크 엣지에서 AWS 컴퓨팅 및 스토리지를 사용하여, 5G 기반 모바일 디바이스 및 사용자에게 한 자리 밀리 초 지연 시간을 제공하는 애플리케이션 제공 가능</li>
<li class="">AWS Outposts 기반</li>
<li class="">AWS 리전과 통신사 5G  망과 직접 연결</li>
<li class="">특징
<ul>
<li class="">5G  단말기 사용자를 위한 광대역 콘텐츠 서비스 제공</li>
<li class="">통신사 5G 망 관리 데이터 센터</li>
<li class="">AWS 리전에서 직접 애플리케이션 배포 및 관리</li>
</ul>
</li>
</ul>
</li>
<li class="">AWS Kendra
<ul>
<li class="">기업 내부 문서 및 데이터에 대한 기계 학습 기반 분석 기반 엔터프라이즈 검색 서비스</li>
<li class="">다양한 데이터 소스 ( S3, Sharepoint, 파일, 서버, HTTP 등 )</li>
<li class="">간단한 API 및 콘솔 코드 샘플 제공</li>
<li class="">아직 한국어는 지원하지 않음</li>
</ul>
</li>
<li class="">Amazon Braket
<ul>
<li class="">과학자와 개발자가 양자 컴퓨팅을 쉽게 탐색하고 실험 할 수 있는 완전 관리형 서비스</li>
<li class="">양자 알고리즘을 설계, 테스트 및 실행하기 위한 단일 환경</li>
<li class="">클라우드 기반 <strong>양자컴퓨팅</strong> 개발 환경</li>
</ul>
</li>
<li class="">AWS DeepComposer
<ul>
<li class="">세계 최초 기계 학습 기반 음악 연주 서비스로서 건반과 장르별 반주 생성을 통해 원하는 장르의 음악 작곡 서비스</li>
<li class="">GEN 학습법을 가지고 반주를 만들어주는 서비스</li>
</ul>
</li>
<li class="">AWS DeepRacer Evo &amp; New Challenge
<ul>
<li class="">클라우드 기반 3D 레이싱 시뮬레이터, 강화 학습으로 움직이는 1/18 비율의 완전 자율 경주용 자동차 및 글로벌 레이싱 리그르 통해 기계 학습 경험 제공</li>
</ul>
</li>
<li class="">AWS SageMaker Studio
<ul>
<li class="">기계 학습 모델 개발 및 배포를 위한 최초의 완전 통합 개발 환경 ( IDE )</li>
<li class="">손쉬운 기계 학습 모델 생성, 훈련 및 서비스 배포 완전 관리 서비스</li>
<li class="">특징
<ul>
<li class="">자동 ML 모델 생성</li>
<li class="">고품질 ML 모델 구성</li>
</ul>
</li>
<li class="">기능
<ul>
<li class="">Notebook</li>
<li class="">Expreiment</li>
<li class="">Processing</li>
<li class="">Debugger</li>
<li class="">Model Monitor</li>
<li class="">Auto Pilot</li>
</ul>
</li>
</ul>
</li>
<li class="">AWS Fargate for Amazon EKS
<ul>
<li class="">서버리스 Kube 컨테이너를 안전하고 안정적으로 대규모로 실행할 수 있는 방법</li>
<li class="">특징
<ul>
<li class="">단순화된 배포, 관리 및 확장 기능</li>
<li class="">모든 포드에 대한 강력한 보안 격리</li>
<li class="">응용 프로그램 구축에 집중 가능한 서버리스</li>
</ul>
</li>
<li class="">Fargate Spot</li>
<li class="">ECS Capacity Providers</li>
<li class="">ECS CLI 2.0</li>
<li class="">Cluster AutoScaling</li>
</ul>
</li>
<li class="">Amazon CodeGuru
<ul>
<li class="">소스 코드 리뷰 및 높은 비용이나 오류를 유발하는 코드 수정 또는 개선을 자동으로 해주는 개발팀을 위한 인공 지능 서비스</li>
<li class="">특징
<ul>
<li class="">Reviewer</li>
<li class="">비용 기반 판별</li>
<li class="">Profiler</li>
<li class="">자바 언어 지원</li>
</ul>
</li>
</ul>
</li>
<li class="">비지니스에 영향을 주는 AI 서비스
<ul>
<li class="">Amazon Personalize
<ul>
<li class="">높은 정확성의 시계열 예측 서비스 ( <a href="http://amazon.com/" target="_blank" rel="noopener noreferrer" class="">Amazon.com</a> 에서 사용된것과 동일한 기술을 기반 )</li>
</ul>
</li>
<li class="">Amazon Fraud Detector
<ul>
<li class="">온라인 결제 사기 및 가짜 계정 생성과 같은 사기성 활동을 쉽게 식별할 수 있는 완전 관리형 AI 서비스</li>
</ul>
</li>
<li class="">Contact Lens for Amazon Connect
<ul>
<li class="">고객 대화에 대한 음성 인식, 자연어 처리를 통한 감정과 추세를 이해하는 Amazon Connect 용 ML 분석 기능</li>
<li class="">아직 한국에 출시 되지 않음</li>
</ul>
</li>
</ul>
</li>
<li class="">서버리스 애플리케이션 개발 플랫폼 지원
<ul>
<li class="">Tool
<ul>
<li class="">IDE
<ul>
<li class="">AWS Toolkit for (PyCharm, IntelliJ, VS Code)</li>
</ul>
</li>
<li class="">AWS Amplify</li>
<li class="">Serverless</li>
<li class="">FireCracker</li>
</ul>
</li>
<li class="">Service
<ul>
<li class="">Provisioned Concurrency for AWS Lambda
<ul>
<li class="">Cold Start 문제 해소</li>
</ul>
</li>
<li class="">HTTP APIs for Amazon API Gateway</li>
<li class="">Amazon RDS Proxy
<ul>
<li class="">Lambda 함수용 Connection Pool 및 Fail Over 기능 제공을 통한 애플리케이션 가용성 증가</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="heroes-패널-토크---클라우드-기술의-미래">Heroes 패널 토크 - 클라우드 기술의 미래<a href="https://clud.me/blog/aws-community-day-reinvent#heroes-%ED%8C%A8%EB%84%90-%ED%86%A0%ED%81%AC---%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EA%B8%B0%EC%88%A0%EC%9D%98-%EB%AF%B8%EB%9E%98" class="hash-link" aria-label="Heroes 패널 토크 - 클라우드 기술의 미래에 대한 직접 링크" title="Heroes 패널 토크 - 클라우드 기술의 미래에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">AWS 도입 했을 때 무엇이 바뀌는가?
<ul>
<li class="">앞으로 IDC 사업자, Cloud Vendor 만 남게 될것이고, 개인이 직접 구축하는 일은 거의 사라질것이다.</li>
<li class="">AWS 가 복잡해지는 만큼 다양한 방법론과 활용도가 나오고 있고, 더 많은 레이어를 씌워서 간단하게 할 수 있는 방법을 고민하고 있다.</li>
</ul>
</li>
<li class="">AWS  가 처음 출시하고 난 이후 가장 크게 변화된 것?
<ul>
<li class="">애플리케이션이 복잡해지고, 비지니스 로직이 복잡해짐에 따라 서비스가 정말 많아졌다.</li>
<li class="">기존 AWS 는 좀 더 원천적인 기술에 대한 지원을 했었다면, 최근에는 좀 더 애플리케이션 레이어를 신경을 많이 쓰는거같다.
<ul>
<li class="">인프라 → Dev/Ops → 애플리케이션을 대체하는 느낌</li>
<li class="">기존에 AWS 를 접근하는 위주가 인프라를 담당하시는 위주였었다면, 최근 들어서는 개발자들이 좀 더 많은 접근이 있다</li>
<li class="">변화가 많은것은 정말 좋으나, 따라가기 힘들다</li>
</ul>
</li>
</ul>
</li>
<li class="">최근에 어떤 변화를 주시하고 있는가?
<ul>
<li class="">하이브리드 인프라 ( Outposts, Wavelength, Local Zone, AWS VMWare for Cloud ) 가 향후 많은 서비스들을 활용할 수 있는 기능이 될거라 생각</li>
<li class="">대한민국 IT 업계는 퍼포먼스에 대한 화두를 던진다</li>
</ul>
</li>
<li class="">re:Invent 에서 어떤걸 느꼈나?
<ul>
<li class="">기술 변화에 적응을 좀 더 빨리 할 필요가 있다</li>
<li class="">AWS 성장과 함께 전세계 Cloud 변화 트렌드를 읽을 수 있는 기회가 되었다</li>
<li class="">EKS on Fargate
<ul>
<li class="">이 서비스가 나오는것은 당연한 일이고, 예상 가능한 일이였다</li>
<li class="">여기서 가장 중요한것은 <code>Saving Plan</code> 이 같이 따라온점이다</li>
</ul>
</li>
</ul>
</li>
<li class="">Latency 에 대해 고민중인 파트너들이 많다</li>
<li class="">AWS 를 도입 해야하는 이유를 설명한다면?
<ul>
<li class=""><strong>적은 인원</strong>으로 <strong>빠르게</strong> 서비스를 <strong>개발</strong>하고 싶다면 도입해야 한다</li>
<li class="">전세계에서 클라우드의 사용량은 10% 에 불과하다.
<ul>
<li class="">아직 늦지 않았고, 앞으로 더 발전하게 될 것이다</li>
</ul>
</li>
<li class="">온-프레미스인가 클라우드인가 에 대한 질문은 이미 답이 나와있다
<ul>
<li class="">온-프레미스 이든 클라우드 이든 기술은 비슷하고, 비용에 대한 증가폭은 다 다르게 된다</li>
<li class="">클라우드 사용할것인가? 에 대해 고민하는것보다도 어떻게 더 잘 사용할것인가를 고민하는게 좋다</li>
<li class="">전세계 가장 큰 4개의 클라우드 업체는 더욱 더 성장할것이다</li>
<li class="">이미 선택은 와있고, 선택을 단순 1차원적인게 아니라 다각적인 측면에서 고려해봐야 한다</li>
<li class="">사람이 먼저다</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="세션">세션<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%84%B8%EC%85%98" class="hash-link" aria-label="세션에 대한 직접 링크" title="세션에 대한 직접 링크" translate="no">​</a></h2>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="쿠알못이-amazon-eks-로-안정적인-서비스-운영하기--최용호-넥슨코리아-">쿠알못이 Amazon EKS 로 안정적인 서비스 운영하기 ( 최용호, 넥슨코리아 )<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%BF%A0%EC%95%8C%EB%AA%BB%EC%9D%B4-amazon-eks-%EB%A1%9C-%EC%95%88%EC%A0%95%EC%A0%81%EC%9D%B8-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%9A%B4%EC%98%81%ED%95%98%EA%B8%B0--%EC%B5%9C%EC%9A%A9%ED%98%B8-%EB%84%A5%EC%8A%A8%EC%BD%94%EB%A6%AC%EC%95%84-" class="hash-link" aria-label="쿠알못이 Amazon EKS 로 안정적인 서비스 운영하기 ( 최용호, 넥슨코리아 )에 대한 직접 링크" title="쿠알못이 Amazon EKS 로 안정적인 서비스 운영하기 ( 최용호, 넥슨코리아 )에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="내용">내용<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%82%B4%EC%9A%A9" class="hash-link" aria-label="내용에 대한 직접 링크" title="내용에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="master-node">Master Node<a href="https://clud.me/blog/aws-community-day-reinvent#master-node" class="hash-link" aria-label="Master Node에 대한 직접 링크" title="Master Node에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">컴포넌트들은 서로 통신하는게 없어서 컴포넌트가 장애가 발생하더라도 복원되면 문제가 없음</li>
<li class="">하지만 API 서버는 모든 컴포넌트들과 통신하고 있기 때문에 API 서버에 장애가 발생하면 모든 클러스터에 장애가 발생함
<ul>
<li class="">그래서 API 서버는 고가용성을 유지해야함</li>
</ul>
</li>
<li class="">etcd 도 장애가 발생 시 모든 클러스터에 장애가 발생함
<ul>
<li class="">etcd 는 최소 3대를 유지해야 함</li>
<li class="">장애 발생 시 마스터 노드를 선택하는 투표를 하는데, 이를 위해 3대를 함</li>
</ul>
</li>
<li class="">Amazon EKS 가 <code>Master Node</code> 를 다 관리 해줌 ( 접속 조차 할 필요가 없음 )</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="woker-node">Woker Node<a href="https://clud.me/blog/aws-community-day-reinvent#woker-node" class="hash-link" aria-label="Woker Node에 대한 직접 링크" title="Woker Node에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Kubelet 이 설치되어 있고, cAdvisor 등 을 사용함</li>
<li class="">Node / Container 지표 수집</li>
<li class="">Scheduler 는 Worker Node 의 상태를 확인하고 Node 에 Pod 를 할당함</li>
<li class=""><code>Amazon EKS Node Groups</code> 라는 기능이 추가되면서 Auto Scaling, 장애 복구 등을 다 관리해줌</li>
<li class="">EC2 는 사용자 계정에 생성됨</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws-eks">AWS EKS<a href="https://clud.me/blog/aws-community-day-reinvent#aws-eks" class="hash-link" aria-label="AWS EKS에 대한 직접 링크" title="AWS EKS에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="설치-방법">설치 방법<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95" class="hash-link" aria-label="설치 방법에 대한 직접 링크" title="설치 방법에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>AWS Management Console</p>
</li>
<li class="">
<p>AWS CLI</p>
</li>
<li class="">
<p><strong>eksctl</strong></p>
<ul>
<li class="">제일 간단하고 쉽게 EKS 클러스터를 생성할 수 있음</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ eksctl create cluster </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">--name</span><span class="token plain"> eks-test </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">--region</span><span class="token plain"> ap-northeast-2 </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">--version</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.14</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token parameter variable" style="color:#36acaa">--managed</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	--asg-access</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>Terraform</p>
<ul>
<li class="">인프라를 코드로 관리할 수 있음</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="인증--권한">인증 &amp; 권한<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%9D%B8%EC%A6%9D--%EA%B6%8C%ED%95%9C" class="hash-link" aria-label="인증 &amp; 권한에 대한 직접 링크" title="인증 &amp; 권한에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">EKS 를 생성한 AWS IAM User  가 Master 권한을 흭득함</li>
<li class=""><code>Kubernetes Admin</code> → kubectl 명령 ( API 호출 ) → <code>Kube Master Node</code> → <code>AWS IAM</code>
<ol>
<li class="">Kubectl 명령</li>
<li class="">Master Node 는 IAM 에 유저 체크</li>
<li class="">Kube RBAC 인증</li>
</ol>
</li>
<li class="">Kube RBAC
<ul>
<li class="">Role ( NameSpace 단위 )</li>
<li class="">Cluster Role ( Cluster 전역의 권한 할당 )</li>
<li class="">AWS IAM 과 유사함</li>
</ul>
</li>
<li class=""><code>Role 생성</code> ( Kube 리소스에 대한 사용 권한 설정, Policy 설정 ) → <code>Role Binding 생성</code> ( 대상 Role 의 권한 부여 )</li>
<li class="">EKS 클러스터를 관리할 관리자가 추가되었다면?
<ul>
<li class="">mapUsers 에 IAM User 추가 및 권한 부여</li>
<li class="">IAM Role 기반 인증 방법
<ol>
<li class="">IAM Role 생성</li>
<li class="">aws-auth ConfigMap 에 추가</li>
<li class="">Cluster Role 또는 Role 생성</li>
<li class="">Role Binding 또는 Cluster Role Binding 생성</li>
<li class="">AWS-Auth 쪽에 Kube RBAC 설정</li>
<li class="">대상 사용자의 kubeconfig 파일에 인증 정보 설정</li>
</ol>
</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="네트워크">네트워크<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC" class="hash-link" aria-label="네트워크에 대한 직접 링크" title="네트워크에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class=""><code>eth0 (10.0.0.2</code>) ↔ <code>docker0 (172.17.0.1)</code> ↔ <code>veth0 (172.17.0.2)</code>,  <code>veth0 (172.0.0.3)</code></li>
<li class=""><code>eth0 (10.0.0.2</code>) ↔ <code>docker0 (172.17.0.2)</code> ↔ <code>veth0 (172.17.0.2)</code>,  <code>veth0 (172.0.0.4)</code></li>
<li class="">Overlay Network ( AWS CNI 사용 )
<ul>
<li class="">실제 VPC에 있는 IP 를 할당 받음</li>
<li class="">VPC 에 IP Range 를 작게 잡으면 Pod 생성을 실패할 수 있음</li>
<li class="">IP Range 에 여유가 있더라도 ENI 의 제약을 받아 Pod 생성을 실패할 수 있음</li>
</ul>
</li>
<li class="">Worker Node
<ul>
<li class="">DaemonSet ( IPAM )
<ul>
<li class="">IPAM 이 할당할 수 있는 아이피 대역이 제한됨</li>
<li class="">IPAM 이 할당할 수 있는 최대를 초과할 경우 ENI 가 추가됨</li>
</ul>
</li>
<li class="">인스턴스 유형에 따라서 ENI 개수가 제한되어 있고, ENI 에 따라서 할당할 수 있는 IP 개수의 제한이 있음</li>
<li class="">Pod 최대 할당 개수 = 인스턴스 유형에 따른 ENI 수 * (ENI 별 IP 수 - 1)</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="volume">Volume<a href="https://clud.me/blog/aws-community-day-reinvent#volume" class="hash-link" aria-label="Volume에 대한 직접 링크" title="Volume에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">안정적인 저장소 준비 → 컨테이너에 안정적인 저장소를 마운트
<ul>
<li class="">EBS, EFS 사용 가능</li>
<li class="">Worker Node 에 있는 File System 을 사용할 수 있음</li>
</ul>
</li>
<li class="">연동 방법
<ol>
<li class=""><code>StorageClass</code> 생성
<ul>
<li class=""><code>volumeBindMode: WaitForFirstCosumer</code> 최초로 컨테이너에 마운트 되는 시점에 EBS 가 생성됨</li>
</ul>
</li>
<li class=""><code>PersistentVolumeClaim</code> 설정</li>
<li class="">컨테이너 마운트</li>
</ol>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="모니터링">모니터링<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81" class="hash-link" aria-label="모니터링에 대한 직접 링크" title="모니터링에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Master Node 의 컴포넌트 들의 로그들은 CloudWatch를 통해 확인할 수 있음 ( BlackBox )
<ul>
<li class="">EKS 클러스터 설정에서 로깅 부분에 보고싶은 로그들을 활성화 해야함</li>
</ul>
</li>
<li class="">Pod 모니터링은 Container Insight 를 사용하면 간단하게 사용 가능
<ul>
<li class="">프로메테우스로 사용할 수 있지만, Container Insight 도 대체가 가능함</li>
<li class="">CloudWatchAgentServerPolicy 설정이 필요함</li>
<li class="">Node, Pod 에 대한 모니터링이 가능함</li>
<li class="">상세한 로그들도 확인이 가능함</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="결론">결론<a href="https://clud.me/blog/aws-community-day-reinvent#%EA%B2%B0%EB%A1%A0" class="hash-link" aria-label="결론에 대한 직접 링크" title="결론에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">힘들고 어려운 부분들은 대부분 Amazon EKS 가 관리해줌</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws-fargate-on-eks-실전-사용하기--용찬호-데브시스터즈-">AWS Fargate on EKS 실전 사용하기 ( 용찬호, 데브시스터즈 )<a href="https://clud.me/blog/aws-community-day-reinvent#aws-fargate-on-eks-%EC%8B%A4%EC%A0%84-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0--%EC%9A%A9%EC%B0%AC%ED%98%B8-%EB%8D%B0%EB%B8%8C%EC%8B%9C%EC%8A%A4%ED%84%B0%EC%A6%88-" class="hash-link" aria-label="AWS Fargate on EKS 실전 사용하기 ( 용찬호, 데브시스터즈 )에 대한 직접 링크" title="AWS Fargate on EKS 실전 사용하기 ( 용찬호, 데브시스터즈 )에 대한 직접 링크" translate="no">​</a></h2>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="내용-1">내용<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%82%B4%EC%9A%A9-1" class="hash-link" aria-label="내용에 대한 직접 링크" title="내용에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="fargate-on-eks">Fargate On EKS<a href="https://clud.me/blog/aws-community-day-reinvent#fargate-on-eks" class="hash-link" aria-label="Fargate On EKS에 대한 직접 링크" title="Fargate On EKS에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Fargate (ECS)
<ul>
<li class="">완전 관리형 컨테이너 서비스</li>
<li class="">범용 목적의 서버리스 컨테이너</li>
</ul>
</li>
<li class="">EKS
<ul>
<li class="">관리형 쿠버네티스 서비스</li>
<li class="">EC2  노드 그룹을 Worker 로 사용</li>
</ul>
</li>
<li class="">EKS + Fargate
<ul>
<li class="">Fargate 에 EKS 의 App 배포 가능</li>
<li class="">오케스트레이터: Kubernetes</li>
</ul>
</li>
<li class="">Control Plane + Data Plane 의 완전한 Serverless</li>
<li class="">관리해야 할 EC2 Instance 가 존재하지 않음
<ul>
<li class="">완전한 서버리스형 쿠버네티스 서비스</li>
<li class="">coreDNS, add-on 등을 모두 Fargate 에 Deploy 가능</li>
<li class="">기존 Node Group 과 함께 WorkLoad 운영 가능  ( 하이브리드 운영 가능 )</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="장점">장점<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%9E%A5%EC%A0%90" class="hash-link" aria-label="장점에 대한 직접 링크" title="장점에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">관리의 복잡도가 줄어든다
<ul>
<li class="">Cluster AutoScaler 를 사용할 필요가 없음</li>
<li class="">비용 청구의 단위가 Pod  의 실행 시간이 된다</li>
<li class="">Pod 를 사용해도 VM 수준의 격리가 가능
<ul>
<li class="">Fargate 의 내부 구조에 의함</li>
</ul>
</li>
<li class="">기존 애플리케이션의 변경 없이 Fargate 로 이전 가능</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="단점">단점<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%8B%A8%EC%A0%90" class="hash-link" aria-label="단점에 대한 직접 링크" title="단점에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Resource 상한선 존재 ( 최대 4vCPU, 30GB 메모리 )</li>
<li class="">Stateful한 workload 사용 불가능</li>
<li class="">Daemonset 을 비롯한  Privileged Pod 사용 불가능</li>
<li class="">NLB / ELB 사용 불가능
<ul>
<li class="">ELB + Ingree 조합을 사용할 수 있음</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="use-case">Use Case<a href="https://clud.me/blog/aws-community-day-reinvent#use-case" class="hash-link" aria-label="Use Case에 대한 직접 링크" title="Use Case에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Stateless 하고 리소스를 크게 요구하지 않으며 특별한 권한이 필요 없는 workload 에 적합함</li>
<li class="">Hybrid 로 구성
<ul>
<li class="">Fargate On EKS 에는 Stateless 한 서버</li>
<li class="">EC2 에는 Stateful 한 서버</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="사용-방법">사용 방법<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95" class="hash-link" aria-label="사용 방법에 대한 직접 링크" title="사용 방법에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">현재 버지니아, 오하이오, 아일랜드, 도쿄에서 지원</li>
<li class="">EKS 클러스터 1.14 이상</li>
<li class="">Fargate Profile 생성 ( Fargate 에 Pod 를 생성하는 조건을 명시 )
<ul>
<li class="">생성하는데 30초 ~ 1분 정도 걸림</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="fargate-on-eks-사용해보기--demo-영상-">Fargate On EKS 사용해보기 ( Demo 영상 )<a href="https://clud.me/blog/aws-community-day-reinvent#fargate-on-eks-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0--demo-%EC%98%81%EC%83%81-" class="hash-link" aria-label="Fargate On EKS 사용해보기 ( Demo 영상 )에 대한 직접 링크" title="Fargate On EKS 사용해보기 ( Demo 영상 )에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">EC2 Node Group 으로 띄우는것보다 훨씬 빠르게 스케일링이 가능함</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="fargate-on-eks-내부-구조-deep-dive">Fargate On EKS 내부 구조 Deep Dive<a href="https://clud.me/blog/aws-community-day-reinvent#fargate-on-eks-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0-deep-dive" class="hash-link" aria-label="Fargate On EKS 내부 구조 Deep Dive에 대한 직접 링크" title="Fargate On EKS 내부 구조 Deep Dive에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="네트워크-구조">네트워크 구조<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B5%AC%EC%A1%B0" class="hash-link" aria-label="네트워크 구조에 대한 직접 링크" title="네트워크 구조에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>물리 서버 ↔ VM 수준의 가상화 레이어 ↔ Fargate 에이전트 ↔ 컨테이너 런타임 ( docker 등 )</p>
<ul>
<li class="">Fargate 는 1개의 컨테이너에 2개 이상의 Task 를 올리는것을 허용하지 않음</li>
</ul>
</li>
<li class="">
<p>1개의 Pod = 1개의 Node</p>
<ul>
<li class="">IP 절약 측면에서 이점</li>
<li class="">VM 수준의 격리 가능</li>
</ul>
</li>
<li class="">
<p>Maximum Node: 5,000개</p>
<ul>
<li class="">Kube 는 최대 5천개의 Pod 만 사용 가능</li>
</ul>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-1-26ac1a24425cc177c4a0c6a5149f959c.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="스케줄링">스케줄링<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" class="hash-link" aria-label="스케줄링에 대한 직접 링크" title="스케줄링에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">스케줄링 순서
<ol>
<li class="">Pod 생성 요청</li>
<li class="">Admission Controller for Fargate</li>
<li class="">변경된 Pod Spec</li>
<li class="">Fargate Scheduler</li>
<li class="">Fargate Pod 할당</li>
</ol>
</li>
<li class="">보이지 않는 AWS Admission Controller 가 Pod Spec 을 변경</li>
<li class="">Pod Spec 에 compute-type 주석과 Fargate Profile 을 함께 사용할 경우
<ul>
<li class="">compute-type 주석의 우선순위가 더 높음 ( 강제로 EC2 에 생성 )</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="요금-체계">요금 체계<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%9A%94%EA%B8%88-%EC%B2%B4%EA%B3%84" class="hash-link" aria-label="요금 체계에 대한 직접 링크" title="요금 체계에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Resource + 256MB ( 쿠버네티스 컴포넌트 )
<ul>
<li class="">과금 되는 리소스 타입 0.5vCPU / 1GB</li>
</ul>
</li>
<li class="">EC2 인스턴스보다 좀 더 Find-Grained 한 리소스 사용 가능</li>
<li class="">Burst  시나리오에서의 동작 유의 필요
<ul>
<li class="">Best Effort, Bustable QoS 클래스의 Pod 의 경우, Limit 이 의미가 없음</li>
<li class="">요금 체계는 <code>Request</code> 를 기준으로 함</li>
</ul>
</li>
<li class="">무조건 Fargate On EKS 가 저렴하지 않을 수 있음
<ul>
<li class="">Fargate On EKS 를 위한 Spot Instance, Saving Plan 지원 예정</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="결론-1">결론<a href="https://clud.me/blog/aws-community-day-reinvent#%EA%B2%B0%EB%A1%A0-1" class="hash-link" aria-label="결론에 대한 직접 링크" title="결론에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class="">Fargate On EKS 는 stateless 한 workload 를 수행하기에 적합</li>
<li class="">EKS 에서 Fargate + EC2 를 혼합해 사용 가능
<ul>
<li class="">stateless + stateful 의 혼합형 workload 구성 가능</li>
</ul>
</li>
<li class="">여러분의 용도에 맞게, 좀 더 저렴한 방법을 선택</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws-기반-서버리스-데이터레이크-구축하기--김진웅-sk-cc-">AWS 기반 서버리스 데이터레이크 구축하기 ( 김진웅, SK C&amp;C )<a href="https://clud.me/blog/aws-community-day-reinvent#aws-%EA%B8%B0%EB%B0%98-%EC%84%9C%EB%B2%84%EB%A6%AC%EC%8A%A4-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%ED%81%AC-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0--%EA%B9%80%EC%A7%84%EC%9B%85-sk-cc-" class="hash-link" aria-label="AWS 기반 서버리스 데이터레이크 구축하기 ( 김진웅, SK C&amp;C )에 대한 직접 링크" title="AWS 기반 서버리스 데이터레이크 구축하기 ( 김진웅, SK C&amp;C )에 대한 직접 링크" translate="no">​</a></h2>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="내용-2">내용<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%82%B4%EC%9A%A9-2" class="hash-link" aria-label="내용에 대한 직접 링크" title="내용에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-플라이휠">데이터 플라이휠<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%94%8C%EB%9D%BC%EC%9D%B4%ED%9C%A0" class="hash-link" aria-label="데이터 플라이휠에 대한 직접 링크" title="데이터 플라이휠에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">Virtuous Cycle ( 선순환 )</li>
<li class="">User → Data → Smarter Algorithms → Better Product → User ...</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-분석의-딜레마">데이터 분석의 딜레마<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EC%9D%98-%EB%94%9C%EB%A0%88%EB%A7%88" class="hash-link" aria-label="데이터 분석의 딜레마에 대한 직접 링크" title="데이터 분석의 딜레마에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">데이터로 하고 싶은 일
<ul>
<li class="">마케팅 / 광고 최적화, 개인화</li>
<li class="">고객 이탈 방지</li>
<li class="">원인 분석</li>
<li class="">매출 증대</li>
<li class="">성과 측정</li>
<li class="">트렌드 파악 / 예측</li>
<li class="">쉽고 편한 분석</li>
</ul>
</li>
<li class="">이미 겪고 있거나 예상되는 문제들
<ul>
<li class="">데이터 한군데 저장 어려움</li>
<li class="">다양한 데이터 포맷 정제 필요</li>
<li class="">일단 실험에 드는 부담</li>
<li class="">레거시 vs 신규 시스템</li>
<li class="">기술 내재화 어려움</li>
<li class="">채용 어려움 ( 인력 확보가 어려움 )</li>
<li class="">시간도 돈도 없음</li>
<li class="">법과 규제에 따른 데이터 활용 제약 ( 공유, 식별 )</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-레이크-정의">데이터 레이크 정의<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A0%88%EC%9D%B4%ED%81%AC-%EC%A0%95%EC%9D%98" class="hash-link" aria-label="데이터 레이크 정의에 대한 직접 링크" title="데이터 레이크 정의에 대한 직접 링크" translate="no">​</a></h4>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-2-ae53a81c8222735a81d1855c3f66446d.webp" width="2048" height="1536" class="img_ev3q"></p>
<ul>
<li class="">
<p>AWS 가 정의한 데이터 레이크 : 정형화 또는 비정형화 된 모든 데이터를 중앙 집중화 시킨 것</p>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-3-a4089031599ceae783eddf01e0a18226.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-레이크-데이터-옵스">데이터 레이크, 데이터 옵스<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A0%88%EC%9D%B4%ED%81%AC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%98%B5%EC%8A%A4" class="hash-link" aria-label="데이터 레이크, 데이터 옵스에 대한 직접 링크" title="데이터 레이크, 데이터 옵스에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">데이터 분석을 하는 시간을 줄이고 품질을 줄이기 위해서 모든 역량을 투입하고, 그 역량을 갖기 위해서 자동화 시키고 프로세스 기반의 방법론</li>
<li class="">DataOps Manifesto
<ol>
<li class="">지속적으로 고객을 만족시켜라</li>
<li class="">분석을 가치있게 생각해라</li>
<li class="">변호 수용</li>
<li class="">다양한 역할, 기술, 도구 수용</li>
<li class="">매일 협력</li>
<li class="">자기주도</li>
<li class="">영중주의를 줄여라</li>
<li class="">반성하라</li>
<li class="">분석은 코드다</li>
<li class="">결합하라</li>
<li class="">재현 가능하게 만들어라</li>
<li class="">비용 최소화</li>
<li class="">단순성</li>
<li class="">분석은 제조와 같다</li>
<li class="">품질 제일 중요</li>
<li class="">품질 및 성능을 모니터링</li>
<li class="">재사용</li>
<li class="">사이클 타임을 개선</li>
</ol>
</li>
<li class="">이상적인 DataOps
<ul>
<li class="">목표를 중심으로 스스로 조직</li>
<li class="">도구, 데이터, 인력 등 모두 장악이 필요함</li>
<li class="">모든 데이터를 한곳으로 다 모으고, 다양한 이해 관계자와 함께 데이터를 활용할 수 있는 플랫폼을 개발</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="아키텍처">아키텍처<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98" class="hash-link" aria-label="아키텍처에 대한 직접 링크" title="아키텍처에 대한 직접 링크" translate="no">​</a></h4>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-4-f67edec9dbb76aa36337a64cf33ce79f.webp" width="2048" height="1536" class="img_ev3q"></p>
<ul>
<li class="">설계 고려 사항
<ul>
<li class="">No-Ops : 관리형 서비스를 사용</li>
<li class="">GitOps : 모든 인프라, 코드, 스크립트들을 관리</li>
<li class="">Automation : 자동화</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="s3-데이터-레이크">S3 데이터 레이크<a href="https://clud.me/blog/aws-community-day-reinvent#s3-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A0%88%EC%9D%B4%ED%81%AC" class="hash-link" aria-label="S3 데이터 레이크에 대한 직접 링크" title="S3 데이터 레이크에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">구성 사례: AWS Glue 를 사용하여 완전한 서버리스 데이터 웨어하우스로 전환 ( <a href="http://woot.com/" target="_blank" rel="noopener noreferrer" class="">woot.com</a> 예시 )</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="s3-기반-수집-처리-분석">S3 기반 수집, 처리, 분석<a href="https://clud.me/blog/aws-community-day-reinvent#s3-%EA%B8%B0%EB%B0%98-%EC%88%98%EC%A7%91-%EC%B2%98%EB%A6%AC-%EB%B6%84%EC%84%9D" class="hash-link" aria-label="S3 기반 수집, 처리, 분석에 대한 직접 링크" title="S3 기반 수집, 처리, 분석에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-수집">데이터 수집<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%88%98%EC%A7%91" class="hash-link" aria-label="데이터 수집에 대한 직접 링크" title="데이터 수집에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p><code>Batch</code> 서비스를  활용</p>
<ul>
<li class="">어떤 규모로든 확장 가능한 완전 관리형 배치 컴퓨팅</li>
</ul>
</li>
<li class="">
<p>구성 사례: 모바일 앱 데이터를 수집하기 위한 타 클라우드 연동 아키텍처</p>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-5-d6eee77334911f316125d131a8f2700b.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
<li class="">
<p>구성 사례: 외부 API 연동 아키텍처 ( Fully Managed Service )</p>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-6-ab3f3a32a6f8435eb00e93f7250f2883.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
<li class="">
<p>스트리밍 데이터 ( Kinesis Data Firehose )</p>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-7-e332b0df227bd5d5bb5fd7a396fe58a9.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-처리">데이터 처리<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B2%98%EB%A6%AC" class="hash-link" aria-label="데이터 처리에 대한 직접 링크" title="데이터 처리에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p>비정형 데이터 → 정형 데이터 rhksfl</p>
</li>
<li class="">
<p>Glue 서비스를 적극 사용</p>
<ul>
<li class="">분석을 위해 손쉽게 데이터를 준비하고 로드할 수 있게 지원하는 완전관리형 ETL ( 추출, 변환, 로드 ) 서비스</li>
</ul>
</li>
<li class="">
<p>구성 사례: 이벤트 기반 Glue 파이프라인 구성</p>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-8-27db34988f6659aa4f38fdf758ffd750.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="데이터-분석">데이터 분석<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D" class="hash-link" aria-label="데이터 분석에 대한 직접 링크" title="데이터 분석에 대한 직접 링크" translate="no">​</a></h4>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-9-5ec1dd613337a13781806dae0b187518.webp" width="2048" height="1536" class="img_ev3q"></p>
<ul>
<li class="">
<p>SageMaker</p>
<ul>
<li class="">기계 학습 모델을 빠르고 쉽게 구축, 훈련하고 배포까지 지원하는 서비스</li>
</ul>
</li>
<li class="">
<p>SageMaker Jupyter 노트북: 모델 배치, 테스트, 검증</p>
<ul>
<li class="">Jupyter 샌드박스 제공</li>
<li class="">LifeCycle 구성 스크립트 활용하여 사전 환경 구성</li>
<li class="">사용량 빌링을 위한 Cost Explorer API 연동</li>
<li class="">Assume Role 을 활용한 원격 Account 분석환경 구성</li>
</ul>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-10-6f8e651d076ac4ca2187cb174e24029d.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
<li class="">
<p>SageMaker Training</p>
<ul>
<li class="">원하는 알고리즘으로 학습 수행 및 모델 저장</li>
</ul>
</li>
<li class="">
<p>엔드포인트는 지속 실행 비용 발생. Transform 은 실제 실행 때만 발생</p>
</li>
<li class="">
<p>BI ( Business Intelligence )</p>
<ul>
<li class="">QuickSight
<ul>
<li class="">완전관리형 클라우드 기반 BI 서비스</li>
</ul>
</li>
<li class="">SPICE ( QuickSight 용 인메모리 최적화 계산 엔진 ) 을 활용하여 주기적인 업데이트</li>
<li class="">3rd Party BI 활용 : RedShift - Trableau Server - 포털 연동</li>
</ul>
</li>
<li class="">
<p>데이터 포털 개발</p>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-11-fc8b95dc65ff0729e068b535088f0301.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="si-회사에서의-데이터-레이크">SI 회사에서의 데이터 레이크<a href="https://clud.me/blog/aws-community-day-reinvent#si-%ED%9A%8C%EC%82%AC%EC%97%90%EC%84%9C%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A0%88%EC%9D%B4%ED%81%AC" class="hash-link" aria-label="SI 회사에서의 데이터 레이크에 대한 직접 링크" title="SI 회사에서의 데이터 레이크에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">
<p>Fully Managed Service 를 이용해서 단기적으로 서비스를 만들려고 했음</p>
</li>
<li class="">
<p>아키텍처</p>
<p><img decoding="async" loading="lazy" alt="AWS Community Day - re 특집" src="https://clud.me/assets/images/image-12-392932690669034682d5a28d65f778c5.webp" width="2048" height="1536" class="img_ev3q"></p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="결론-2">결론<a href="https://clud.me/blog/aws-community-day-reinvent#%EA%B2%B0%EB%A1%A0-2" class="hash-link" aria-label="결론에 대한 직접 링크" title="결론에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class="">S3 기반의 서버리스 아키텍처도 충분히 적용 가능</li>
<li class="">완전 관리형 서비스만이 정답은 아님 ( Challenge )
<ul>
<li class="">기존 Hadoop ecosystem 통합</li>
<li class="">기존 조직과의 R&amp;R ( 정보 보호, 개발, 인프라 등 )</li>
</ul>
</li>
<li class="">서버리스 컴퓨팅 자원: EKS On Fargate 검토</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws-sam으로-서버리스-아키텍처-운영하기--이재면-mymusictaste-">AWS SAM으로 서버리스 아키텍처 운영하기 ( 이재면, Mymusictaste )<a href="https://clud.me/blog/aws-community-day-reinvent#aws-sam%EC%9C%BC%EB%A1%9C-%EC%84%9C%EB%B2%84%EB%A6%AC%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EC%9A%B4%EC%98%81%ED%95%98%EA%B8%B0--%EC%9D%B4%EC%9E%AC%EB%A9%B4-mymusictaste-" class="hash-link" aria-label="AWS SAM으로 서버리스 아키텍처 운영하기 ( 이재면, Mymusictaste )에 대한 직접 링크" title="AWS SAM으로 서버리스 아키텍처 운영하기 ( 이재면, Mymusictaste )에 대한 직접 링크" translate="no">​</a></h2>
<p><br>
\</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="내용-3">내용<a href="https://clud.me/blog/aws-community-day-reinvent#%EB%82%B4%EC%9A%A9-3" class="hash-link" aria-label="내용에 대한 직접 링크" title="내용에 대한 직접 링크" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws-sam-을-사용한-이유">AWS SAM 을 사용한 이유<a href="https://clud.me/blog/aws-community-day-reinvent#aws-sam-%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%9D%B4%EC%9C%A0" class="hash-link" aria-label="AWS SAM 을 사용한 이유에 대한 직접 링크" title="AWS SAM 을 사용한 이유에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">API Gateway, DynamoDB, SNS, SQS, Lambda 로 구성된 서비스 개발이 진행</li>
<li class="">Infrastrcture as Code 를 통해서 배포를 구성</li>
<li class="">이미 ECS 로 구성된 Resources 들이 Terraform 으로 구성되어 있었음</li>
<li class=""><code>sam local</code> 을 이용해서 로컬 환경에서 테스트 &amp; 디버깅을 해볼 수 있음
<ul>
<li class=""><code>sam local start-api</code></li>
<li class=""><code>sam local start-api --docker-network</code></li>
<li class=""><code>sam local generate-event dynamodb update &gt; event.json</code></li>
<li class=""><code>sam local invoke --event event.json SendMessage</code></li>
<li class=""><code>sam local lambda</code></li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="sam--serverless-application-model-">SAM ( Serverless Application Model )<a href="https://clud.me/blog/aws-community-day-reinvent#sam--serverless-application-model-" class="hash-link" aria-label="SAM ( Serverless Application Model )에 대한 직접 링크" title="SAM ( Serverless Application Model )에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Serverless 를 위한 Tool 로 편리하게 Abstraction 되어 있다.</li>
<li class="">SAM Template
<ul>
<li class="">Globals 로 공통적인 Config 설정</li>
<li class="">Alias, Versioning 관리 가능</li>
<li class="">Canary 배포 가능</li>
</ul>
</li>
<li class="">다양한 Resource 들을 지원하고, CloudFormation Syntax 를 그대로 사용할 수 있다</li>
<li class=""><code>--use-container</code> 옵션을 통해 <code>sam build</code> 를 하면 Amazon Linux Docker Image 를 이용해서 빌드</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cloudformation-기능-설명">CloudFormation 기능 설명<a href="https://clud.me/blog/aws-community-day-reinvent#cloudformation-%EA%B8%B0%EB%8A%A5-%EC%84%A4%EB%AA%85" class="hash-link" aria-label="CloudFormation 기능 설명에 대한 직접 링크" title="CloudFormation 기능 설명에 대한 직접 링크" translate="no">​</a></h3>
<ul>
<li class="">AWS SAM 은 AWS::Serverless 의 Resource 들이 cfn 이랑 호환될 수 있도록 변환한다</li>
<li class="">cfn 에서 지원하는 기능들을 대부분 사용할 수 있다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="parameters">Parameters<a href="https://clud.me/blog/aws-community-day-reinvent#parameters" class="hash-link" aria-label="Parameters에 대한 직접 링크" title="Parameters에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Parameters 로 Input 을 Dynamic 하게 설정하여 Stack 을 생성 또는 업데이트 할 수 있다</li>
<li class="">System Manager Parameter Store 에 저장한 값을 쉽게 연동하여 cfn parameter 값으로 사용할 수 있다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="mappings">Mappings<a href="https://clud.me/blog/aws-community-day-reinvent#mappings" class="hash-link" aria-label="Mappings에 대한 직접 링크" title="Mappings에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">Key 값 별로 미리 Value 를 정의해놓고 사용할 수 있다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="conditions">Conditions<a href="https://clud.me/blog/aws-community-day-reinvent#conditions" class="hash-link" aria-label="Conditions에 대한 직접 링크" title="Conditions에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">조건을 만족하는 경우에만 Resource 를 생성할 수 있도록 설정할 수 있다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="nested-stacks">Nested Stacks<a href="https://clud.me/blog/aws-community-day-reinvent#nested-stacks" class="hash-link" aria-label="Nested Stacks에 대한 직접 링크" title="Nested Stacks에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">공통된 Resource 를 정의한 Template 을 재사용하여 만들 수 있다</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="stacksets">StackSets<a href="https://clud.me/blog/aws-community-day-reinvent#stacksets" class="hash-link" aria-label="StackSets에 대한 직접 링크" title="StackSets에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">StackSets 으로 여러 Region 과 여러 Acoount 에 Stack 을 생성하고 관리할 수 있음</li>
<li class="">Organizations 에서 Service Mnaged Permission 으로 관리될 수 있을거라 생각</li>
<li class="">Organization Unit ( OU ) 별로 Stack 을 자동 배포할 수 있게 될 예정
<ul>
<li class="">OU 에 Account 가 추가되면 자동으로 Stack 이 배포되고, Account가 OU 에서 빠지면 자동으로 Stack 이 지워질 수 있음</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="아쉬웠던-점">아쉬웠던 점<a href="https://clud.me/blog/aws-community-day-reinvent#%EC%95%84%EC%89%AC%EC%9B%A0%EB%8D%98-%EC%A0%90" class="hash-link" aria-label="아쉬웠던 점에 대한 직접 링크" title="아쉬웠던 점에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">이미 존재하는 Resource 들을 Stack 에 포함시키고 싶을 때
<ul>
<li class=""><code>resource import</code> 2019년 11월에 발표됨</li>
<li class="">SAM Template 은 Transform 되어야 하는 것 때문에 다음과 같은 에러 발생</li>
<li class="">SAM 은 Import 를 지원하는 Resource 들이 제한적임</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pipeline">Pipeline<a href="https://clud.me/blog/aws-community-day-reinvent#pipeline" class="hash-link" aria-label="Pipeline에 대한 직접 링크" title="Pipeline에 대한 직접 링크" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="pipeline-1">Pipeline<a href="https://clud.me/blog/aws-community-day-reinvent#pipeline-1" class="hash-link" aria-label="Pipeline에 대한 직접 링크" title="Pipeline에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">User → Template → Version Control → Test → Deploy ( Staging ) → Deploy ( Production )</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="구성에-도움이-되는-tool">구성에 도움이 되는 Tool<a href="https://clud.me/blog/aws-community-day-reinvent#%EA%B5%AC%EC%84%B1%EC%97%90-%EB%8F%84%EC%9B%80%EC%9D%B4-%EB%90%98%EB%8A%94-tool" class="hash-link" aria-label="구성에 도움이 되는 Tool에 대한 직접 링크" title="구성에 도움이 되는 Tool에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class=""><code>cfn-lint</code>
<ul>
<li class="">CloudFormation Linter</li>
<li class="">.cfnlintrc 이름의 YAML 파일에 다양한 옵션을 설정할 수 있음</li>
</ul>
</li>
<li class=""><code>change-set</code>
<ul>
<li class="">cfn 에서 change sets 으로 Stack 에 어떤 부부닝 업데이트 될 지 적용하기 전에 알 수 있다</li>
</ul>
</li>
<li class=""><code>TaskCat</code>
<ul>
<li class="">AWS QuickStart Team 에서 cfn template 을 테스트하기 위해 만들어진 tool</li>
<li class="">실제 Stack 을 만들고 결과 리포트를 생성</li>
</ul>
</li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="컨퍼런스" term="컨퍼런스"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Session Manager 알아보기]]></title>
        <id>https://clud.me/blog/aws-session-manager</id>
        <link href="https://clud.me/blog/aws-session-manager"/>
        <updated>2020-01-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AWS SSM (System Manager) 는 EC2, S3, RDS 인스턴스 를 모니터링 & 관리 를 할 수 있는 서비스 이다.]]></summary>
        <content type="html"><![CDATA[
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="session-manager">Session Manager<a href="https://clud.me/blog/aws-session-manager#session-manager" class="hash-link" aria-label="Session Manager에 대한 직접 링크" title="Session Manager에 대한 직접 링크" translate="no">​</a></h2>
<p>AWS SSM (System Manager) 는 EC2, S3, RDS 인스턴스 를 모니터링 &amp; 관리 를 할 수 있는 서비스 이다.</p>
<p>이 서비스 중 한가지 기능으로 <code>Session Manager</code> 라는 기능이 2018년에 추가 되었는데, 사용법을 까먹을가봐 정리해두려 한다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="주절주절">주절주절<a href="https://clud.me/blog/aws-session-manager#%EC%A3%BC%EC%A0%88%EC%A3%BC%EC%A0%88" class="hash-link" aria-label="주절주절에 대한 직접 링크" title="주절주절에 대한 직접 링크" translate="no">​</a></h3>
<p>보통 VPC 를 구성할 때 Public Subnet, Private Subnet 을 나눠서 구성한다.</p>
<p>Private Subnet 은 외부 네트워크와 통신하기 위해 NAT ( Gateway 혹은 Instance ) 를 두는데, 이 Subnet 안에서 생성된 인스턴스들은 퍼블릭 IP 가 없기 때문에 외부에서 바로 접속할 수 없다.</p>
<p>서비스를 운영하다보면 SSH 로 서버에 직접 접속할 일들이 생기게 되는데, Private Subnet 에 있는 서버에 접속할 수 없다보니 Public Subnet 에 Bastion 을 띄우고 Bastion 을 통해 Private Subnet 에 있는 서버에 접속하게 된다.</p>
<p>Bastion Host 에 아무나 접속하면 안되기 때문에 Vault 나 다른 서비스를 통해 인증 과정을 거치기도 하지만, 일반적으로 가장 간단한 PEM 파일을 이용하여 접속한다.</p>
<p>1명에서 서버를 관리할 땐 PEM 파일을 가지고 접속할 수 있지만, 팀원이 증가하면서 PEM 파일을 공유해야 하는 문제가 발생한다. ( <del>PEM 파일이 사라지거나 유출되는 경우 상상도 하기 싫다.</del> )</p>
<p>이러한 문제를 쉽게 해결하기 위해 나온게 <code>Session Manager</code>  이다.</p>
<p>Session Manager 는 Shell 수준의 접근을 지원하는 서비스인데, IAM 권한으로 인증을 하며 Cloud Trail 로 모든 접근에 대한 모니터링을 할 수 있다.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ssm-agent">SSM Agent<a href="https://clud.me/blog/aws-session-manager#ssm-agent" class="hash-link" aria-label="SSM Agent에 대한 직접 링크" title="SSM Agent에 대한 직접 링크" translate="no">​</a></h3>
<p>Session Manager 을 사용하기 위해서는 SSM Agent 가 설치되어 있어야 한다.</p>
<p><code>Amazon Linux 기반 AMI(날짜: 2017.09)</code>, <code>Amazon Linux 2</code>, <code>Ubuntu Server 16.04</code>, <code>Ubuntu Server 18.04 LTS</code> 는 기본적으로 설치되어 있다.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="수동-설치">수동 설치<a href="https://clud.me/blog/aws-session-manager#%EC%88%98%EB%8F%99-%EC%84%A4%EC%B9%98" class="hash-link" aria-label="수동 설치에 대한 직접 링크" title="수동 설치에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class=""><a href="https://docs.aws.amazon.com/ko_kr/systems-manager/latest/userguide/sysman-manual-agent-install.html" target="_blank" rel="noopener noreferrer" class="">https://docs.aws.amazon.com/ko_kr/systems-manager/latest/userguide/sysman-manual-agent-install.html</a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="iam-role-적용">IAM Role 적용<a href="https://clud.me/blog/aws-session-manager#iam-role-%EC%A0%81%EC%9A%A9" class="hash-link" aria-label="IAM Role 적용에 대한 직접 링크" title="IAM Role 적용에 대한 직접 링크" translate="no">​</a></h3>
<p>인스턴스가  SSM 에 접근할 수 있도록 IAM Role  을 부여해줘야 한다.</p>
<p>기존 Instance Role 이 적용되어 있다면 아래의 정책을 추가해준다.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"Version"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2012-10-17"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"Statement"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"Action"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"ssmmessages:*"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"ssm:UpdateInstanceInformation"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"ec2messages:*"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"Resource"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"*"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"Effect"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Allow"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Instance Role 을 부여한 이후 <code>amazon-ssm-agent</code> 를 재시작해야 한다.</p>
<ul>
<li class="">
<p>Linux</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> restart amazon-ssm-agent</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>Ubuntu</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl restart snap.amazon-ssm-agent.amazon-ssm-agent.service</span><br></div></code></pre></div></div>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="session-manager--시작">Session Manager  시작<a href="https://clud.me/blog/aws-session-manager#session-manager--%EC%8B%9C%EC%9E%91" class="hash-link" aria-label="Session Manager  시작에 대한 직접 링크" title="Session Manager  시작에 대한 직접 링크" translate="no">​</a></h4>
<p>AWS Management Console 에서 System Manager 에 들어가면 좌측에 세션 매니저 (Session Manager) 에 들어가서 시작하면 된다.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="terminal-에서-접속하는-방법">Terminal 에서 접속하는 방법<a href="https://clud.me/blog/aws-session-manager#terminal-%EC%97%90%EC%84%9C-%EC%A0%91%EC%86%8D%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95" class="hash-link" aria-label="Terminal 에서 접속하는 방법에 대한 직접 링크" title="Terminal 에서 접속하는 방법에 대한 직접 링크" translate="no">​</a></h4>
<ul>
<li class="">
<p><code>~/.ssh/config</code> 에 아래의 내용을 추가해준다</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># SSH over Session Manager</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">host</span><span class="token plain"> i-* mi-*</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ProxyCommand </span><span class="token function" style="color:#d73a49">sh</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"</span><br></div></code></pre></div></div>
</li>
<li class="">
<p>접속할 EC2 Instance 의 ID 를 찾아낸 후 SSH 접속하면 된다</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> ec2-user@i-00000000000000000</span><br></div></code></pre></div></div>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="참고">참고<a href="https://clud.me/blog/aws-session-manager#%EC%B0%B8%EA%B3%A0" class="hash-link" aria-label="참고에 대한 직접 링크" title="참고에 대한 직접 링크" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://docs.aws.amazon.com/ko_kr/systems-manager/latest/userguide/session-manager.html" target="_blank" rel="noopener noreferrer" class="">https://docs.aws.amazon.com/ko_kr/systems-manager/latest/userguide/session-manager.html</a></li>
</ul>]]></content>
        <author>
            <name>서동명</name>
            <uri>https://clud.me</uri>
        </author>
        <category label="AWS" term="AWS"/>
    </entry>
</feed>