<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://billiamchoi.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://billiamchoi.github.io/" rel="alternate" type="text/html" /><updated>2025-05-06T15:48:07+00:00</updated><id>https://billiamchoi.github.io/feed.xml</id><title type="html">댄싱코딩</title><subtitle>코딩과 함께 춤을</subtitle><entry><title type="html">[MuleSoft] MuleSoft Hybrid 환경 구축방법에 대해 알아보자</title><link href="https://billiamchoi.github.io/develop/2025/05/06/MuleSoft-Hybrid-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95%EB%B0%A9%EB%B2%95%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90.html" rel="alternate" type="text/html" title="[MuleSoft] MuleSoft Hybrid 환경 구축방법에 대해 알아보자" /><published>2025-05-06T02:05:00+00:00</published><updated>2025-05-06T02:05:00+00:00</updated><id>https://billiamchoi.github.io/develop/2025/05/06/MuleSoft-Hybrid-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95%EB%B0%A9%EB%B2%95%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</id><content type="html" xml:base="https://billiamchoi.github.io/develop/2025/05/06/MuleSoft-Hybrid-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95%EB%B0%A9%EB%B2%95%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90.html"><![CDATA[<h1 id="mulesoft-hybrid-환경-구축-manual">MuleSoft Hybrid 환경 구축 Manual</h1>

<hr />

<h3 id="목차">목차</h3>

<h4 id="1-필요사항">1. 필요사항</h4>

<h4 id="2-서버-구성-및-구동">2. 서버 구성 및 구동</h4>

<h4 id="3-mulesoft-standalone-다운로드e">3. MuleSoft Standalone 다운로드E;</h4>

<h4 id="4-mobaxterm-다운로드">4. MobaXterm 다운로드</h4>

<h4 id="5-mobaxterm을-사용하여-ssh-접속">5. MobaXterm을 사용하여 SSH 접속</h4>

<h4 id="6-mulesoft-standalone-설치">6. MuleSoft Standalone 설치</h4>

<h4 id="7-jdk-17-설치">7. JDK 17 설치</h4>

<h4 id="8-enterprise-라이센스-설치">8. Enterprise 라이센스 설치</h4>

<h4 id="9-enterprise-라이센스-확인-및-뮬서버-구동">9. Enterprise 라이센스 확인 및 뮬서버 구동</h4>

<h4 id="10-필수아님-arm-에이전트-다운로드-및-설치다른-버전의-에이전트가-필요한-경우">10. (필수아님) ARM 에이전트 다운로드 및 설치(다른 버전의 에이전트가 필요한 경우)</h4>

<h4 id="11-arm-agent를-사용하여-runtime-manager에-runtime-engine-등록">11. ARM Agent를 사용하여 Runtime Manager에 Runtime Engine 등록</h4>

<h4 id="12-애플리케이션-배포">12. 애플리케이션 배포</h4>

<h4 id="13-amanypoint-monitoring-agent-설치">13. AM(anypoint monitoring) Agent 설치</h4>

<h4 id="14-mulesoft-proxy-server-설치하여-reverse-proxy-적용">14. MuleSoft Proxy Server 설치하여 Reverse Proxy 적용</h4>

<h4 id="15-필수아님-nginx-설치하여-reverse-proxy-적용">15. (필수아님) Nginx 설치하여 Reverse Proxy 적용</h4>

<h4 id="16-필수아님-aws--azure-서버-클러스터-생성">16. (필수아님) AWS &amp; Azure 서버 클러스터 생성</h4>

<h4 id="17-필수아님-mule-gateway-with-nginx-구성">17. (필수아님) Mule Gateway with Nginx 구성</h4>

<h4 id="18-필수아님-mule-gateway-with-elk-구성">18. (필수아님) Mule Gateway with ELK 구성</h4>

<h4 id="19-troubleshooting">19. Troubleshooting</h4>

<hr />

<h2 id="1-필요사항-1">1. 필요사항</h2>

<p><b>만약 Azure에 구축시</b></p>

<ul>
  <li>Azure VM</li>
  <li>Red Hat Enterprise Linux 9.4 (LVM) - x64 Gen2 (OS)</li>
</ul>

<p><b>만약 AWS에 구축시</b></p>

<ul>
  <li>AWS EC2</li>
  <li>amazon/RHEL-9.5.0_HVM-20241211-x86_64-0-Hourly2-GP3 (OS)</li>
</ul>

<p><b>공통 필요사항</b></p>

<ul>
  <li>MuleSoft Standalone 4.8.1 (설치URL: https://www.mulesoft.com/lp/dl/anypoint-mule-studio)</li>
  <li>MobaXterm</li>
  <li>Nginx (optional)</li>
</ul>

<h2 id="2-서버-구성-및-구동-1">2. 서버 구성 및 구동</h2>

<p>설치할 서버에 따라 서버 구성하고 구동하면 됩니다.</p>

<p>Azure에 설치할 경우, 2.1. Azure에 설치를 보시고</p>

<p>AWS에 설치할 경우, 2.2. AWS에 설치를 보시면 됩니다.</p>

<h3 id="21-azure에-설치">2.1. Azure에 설치</h3>

<p>중요 속성은 다음과 같음</p>

<ul>
  <li>초기 입력창
<img src="/assets/img/1_AzureSetting.png" alt="alt text" /></li>
  <li>확인창
<img src="/assets/img/2_AzureConfirm.png" alt="alt text" /></li>
</ul>

<h4 id="211-azure-중요속성">2.1.1. Azure 중요속성</h4>

<ul>
  <li>지역: Korea Central</li>
  <li>사용자이름: mulesoftuser</li>
  <li>이미지: Red Hat Enterprise Linux 9.4 (LVM) - x64 Gen2</li>
  <li>서버크기: 2 vcpu, 8 GiB 메모리</li>
</ul>

<ol>
  <li>중요속성을 준수하고 AzureVM 생성</li>
  <li>Pem Key도 중요하여 다운받는다.</li>
</ol>

<p>*AzureVM에서 AzureRocky 현재 안됨 (아래 스크린샷 참고)
<img src="/assets/img/3_AzureRockyError.png" alt="alt text" /></p>

<hr />

<h3 id="22-aws에-설치">2.2. AWS에 설치</h3>

<p>중요 속성은 다음과 같음</p>

<ul>
  <li>초기 입력창
<img src="/assets/img/47_aws_instance.png" alt="alt text" /></li>
</ul>

<h4 id="221-aws-중요-속성">2.2.1. AWS 중요 속성</h4>

<ul>
  <li>지역: 아시아 태평양(서울)</li>
  <li>이미지: amazon/RHEL-9.5.0_HVM-20241211-x86_64-0-Hourly2-GP3
(이미지는 위 텍스트로 검색 후, 커뮤니티 AMI 탭에서 선택한다)</li>
  <li>서버크기: t2.small (2 vcpu, 8 GiB 메모리)</li>
</ul>

<ol>
  <li>중요속성을 준수하고 AWS EC2 생성</li>
  <li>Pem Key도 중요하여 새 키 페어 생성하여 다운받는다.</li>
</ol>

<h2 id="3-mulesoft-standalone-다운로드">3. MuleSoft Standalone 다운로드</h2>

<ol>
  <li>
    <p>https://www.mulesoft.com/lp/dl/anypoint-mule-studio 방문하여 아래와 같이 작성 후, 다운로드 클릭
<img src="/assets/img/4_Download.png" alt="alt text" /></p>
  </li>
  <li>
    <p>아래와 같은 이메일이 도착하면 Go to download page를 클릭하여 다운 받는다.
<img src="/assets/img/5_email.png" alt="alt text" /></p>
  </li>
</ol>

<h2 id="4-mobaxterm-다운로드-1">4. MobaXterm 다운로드</h2>

<ol>
  <li>https://mobaxterm.mobatek.net/download.html 에 접속하여 Home Edition MobaXterm을 설치한다.</li>
</ol>

<h2 id="5-mobaxterm을-사용하여-ssh-접속-1">5. MobaXterm을 사용하여 SSH 접속</h2>

<ol>
  <li>
    <p>AzureVM 개요 페이지에서 연결할 공용 IP 주소를 확인한다.</p>
  </li>
  <li>
    <p>MobaXterm을 실행하여 아래와 같이 세션 설정한다.
<img src="/assets/img/6_SessionSetting.png" alt="alt text" /></p>
  </li>
</ol>

<ul>
  <li>Remote host: Azure의 공용 IP 주소 입력</li>
  <li>username: 설정한 username 입력</li>
  <li>Advenced SSH setting 탭에 Use private key 클릭 후 pem key 위치 설정</li>
</ul>

<p>위의 사항을 모두 준수하였으면 OK를 눌러 세션 설정하여 Azure VM 접속한다.</p>

<h2 id="6-mulesoft-standalone-설치-1">6. MuleSoft Standalone 설치</h2>

<ol>
  <li>
    <p>MobaXterm을 통해 AzureVM에 접속하고 rootDirectory에 아까 다운받은 MuleSoftStandone(mule-ee-distribution-standalone-4.8.1.zip)을 Drag &amp; Drop으로 옮긴다.</p>
  </li>
  <li>
    <p>설치파일 압축제거 및 압축파일 제거</p>
  </li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// rootdirectory에 압축풀기
<span class="nv">$ </span>unzip mule-ee-distribution-standalone-4.8.1.zip
// 압축파일 제거
<span class="nv">$ </span><span class="nb">rm</span> <span class="nt">-rf</span> mule-ee-distribution-standalone-4.8.1.zip
</code></pre></div></div>

<ol>
  <li>bash_profile에서 MULE_HOME 환경변수 설정</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// rootdirectory에서 vi로 bashrc 편집
<span class="nv">$ </span>vi .bashrc
// bashrc에 아래와 같이 추가 후 저장
<span class="nb">export </span><span class="nv">MULE_HOME</span><span class="o">=</span>~/mule-enterprise-standalone-4.8.1
</code></pre></div></div>

<ol>
  <li>source 명령어로 변경사항 반영</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">source</span> ~/.bashrc
</code></pre></div></div>

<h2 id="7-jdk-17-설치-1">7. JDK 17 설치</h2>

<ol>
  <li>VM의 root Directory에서 아래 명령어를 입력하여 JDK 17을 다운로드 받는다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>yum <span class="nb">install </span>java-17-openjdk-17.0.13.0.11-4.el9.x86_64
</code></pre></div></div>

<ol>
  <li>환경변수 JAVA_HOME 추가</li>
</ol>

<ul>
  <li>
    <p>cd /usr/lib/jvm을 사용하여 이동하고 ls 명령어를 사용하여 아래 java-17로 시작하는 디렉토리를 찾는다.</p>
  </li>
  <li>
    <p>해당 명령어를 .bashrc에 추가 후 저장한다.</p>
  </li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">JAVA_HOME</span><span class="o">=</span><span class="s2">"/usr/lib/jvm/java-17-openjdk-17.0.13.0.11-4.el9.x86_64"</span>
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="s2">"</span><span class="nv">$JAVA_HOME</span><span class="s2">/bin:</span><span class="nv">$PATH</span><span class="s2">"</span>
</code></pre></div></div>

<ul>
  <li>source 명령어로 변경사항 반영</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">source</span> ~/.bashrc
</code></pre></div></div>

<ol>
  <li>아래 명령어를 사용하여 환경변수 Test를 진행한다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// 해당 명령어는 foreground mode로서 터미널에 콘솔 로그를 출력 합니다.
// Mule이 실행되는 동안에는 터미널에서 추가 명령을 실행할 수 없습니다.
<span class="nv">$ $MULE_HOME</span>/bin/mule
</code></pre></div></div>

<ol>
  <li>성공적으로 테스트 완료되면 아래와 같은 메세지가 터미널에 표시된다.
<img src="/assets/img/7_successdeploy.png" alt="alt text" /></li>
</ol>

<h2 id="8-enterprise-라이센스-설치-1">8. Enterprise 라이센스 설치</h2>

<ol>
  <li>MuleSoft Help Center(https://help.mulesoft.com)를 방문 후 로그인한다.</li>
  <li>상단에 Support를 클릭하여 서포트 페이지 방문한다.</li>
  <li>하단에 License keys를 클릭하여 License 페이지로 이동한다.</li>
  <li>프로젝트의 라이센트 키 클릭 후 다운로드한다.
(형식: license.lic)</li>
  <li>$MULE_HOME/bin 디렉토리로 이동 후 다운받은 license.lic를 해당 디렉토리에 복사 붙여넣기 한다.</li>
  <li>해당 명령어를 입력하여 license를 설치한다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// 상황에 따라, 뮬 standalone 버전넘버는 다를 수 있다.
<span class="nv">$ </span>./mule <span class="nt">-installLicense</span> ~/mule-enterprise-standalone-4.8.1/bin/license.lic
</code></pre></div></div>

<ol>
  <li>성공적으로 설치가 완료되었다면, %MULE_HOME%\conf 디렉토리에 하위에 muleLicenseKey.lic가 보임</li>
</ol>

<h2 id="9-enterprise-라이센스-확인-및-뮬서버-구동-1">9. Enterprise 라이센스 확인 및 뮬서버 구동</h2>

<ol>
  <li>%MULE_HOME%\bin 디렉토리에서 아래와 같은 명령어를 입력하여 MuleSoft 라이센스 확인</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./mule <span class="nt">-verifyLicense</span>
</code></pre></div></div>

<ol>
  <li>
    <p>정상적으로 확인되었으면 아래와 같은 콜솔 메세지 확인할 수 있다.
<img src="/assets/img/8_validLicense.png" alt="alt text" /></p>
  </li>
  <li>
    <p>아래 명령어를 사용하여 뮬서버 구동</p>
  </li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./mule start
</code></pre></div></div>

<h2 id="10-필수아님-arm-에이전트-다운로드-및-설치다른-버전의-에이전트가-필요한-경우-1">10. (필수아님) ARM 에이전트 다운로드 및 설치(다른 버전의 에이전트가 필요한 경우)</h2>

<ol>
  <li>뮬소프트 지원페이지 방문 (https://help.mulesoft.com/s/support)</li>
  <li>중앙에 Download 클릭</li>
  <li>설치할 에이전트를 찾아 작업 열에서 다운로드를 클릭합니다.
<img src="/assets/img/9_muleagent.png" alt="alt text" /></li>
  <li>Mule Runtime을 중지합니다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./mule stop
</code></pre></div></div>

<ol>
  <li>다운로드한 agent-setup-VERSION.zip 파일을 OS 유형에 따라 $MULE_HOME/bin 또는 %MULE_HOME%\bin에 추출합니다. (메시지가 표시되면 충돌하는 모든 파일을 덮어씁니다.)</li>
  <li>$MULE_HOME/bin/amc_setup 또는 %MULE_HOME%\bin\amc_setup.bat을 실행하고 설치에 대한 매개변수를 지정합니다.
지정할 매개변수에 대한 정보는
(https://docs.mulesoft.com/runtime-manager/installing-and-configuring-runtime-manager-agent#amc_setup-parameters)를 참조하세요.</li>
  <li>Mule Runtime을 다시 시작합니다.</li>
  <li>Runtime Manager Agent(ARM Agent)가 $MULE_HOME/plugins 또는 %MULE_HOME%\plugins 디렉터리에 설치됩니다.</li>
</ol>

<h2 id="11-arm-agent를-사용하여-runtime-manager에-runtime-engine-등록-1">11. ARM Agent를 사용하여 Runtime Manager에 Runtime Engine 등록</h2>

<ul>
  <li>ARM Agent는 Mule Runtime Engine을 Runtime Manager에 등록합니다.</li>
  <li>Runtime이 등록된 후에는 Mule이 등록된 특정 환경 및 Anypoint Platform 비즈니스 그룹 내에서 Runtime Manager를 사용하여 관리할 수 있습니다.</li>
  <li>여러 개의 Runtime Manager 비즈니스 그룹이나 환경에 Mule Runtime을 등록할 수 없습니다.</li>
</ul>

<h3 id="111-runtime-manager에-등록">11.1. Runtime Manager에 등록</h3>

<h4 id="필요사항">필요사항</h4>

<ul>
  <li>registration token: Anypoint Platform에서 특정 비즈니스 그룹의 특정 환경을 식별하는 유효한 등록 토큰입니다.</li>
  <li>instance name: 런타임 관리자 콘솔에서 Mule을 식별하는 인스턴스 이름입니다.</li>
</ul>

<p>Any Point Studio로 접속하여 아래 순서대로 진행한다.</p>

<ol>
  <li>Runtime Manager에서 왼쪽 메뉴에서 Servers를 클릭합니다.</li>
  <li>Add Server 버튼을 클릭합니다.</li>
  <li>서버의 고유한 이름을 입력합니다.
<img src="/assets/img/10_add_server.png" alt="alt text" /></li>
  <li>Copy command를 클릭하여 AzureVM $MULE_HOME/bin에서 명령어를 붙여넣고 실행합니다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./amc_setup <span class="nt">-H</span> f608a6a8-515c-4aab-813b-9137a49b7367---1928550 MuleSoftVM1-azure
</code></pre></div></div>

<ol>
  <li>아래 로그와 같이 성공적으로 설정이 완료되었다는 문구 표기되면 정상적으로 설정된 것이다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Mule Agent configured successfully
Mule Agent configuration saved successfully
</code></pre></div></div>

<ol>
  <li>다시 뮬서버 재기동</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./mule restart
</code></pre></div></div>

<ol>
  <li>문제없이 서버 설정했으면 서버가 아래와 같이 목록에 추가됩니다.
<img src="/assets/img/11_runtimemanager.png" alt="alt text" /></li>
</ol>

<h2 id="12-애플리케이션-배포-1">12. 애플리케이션 배포</h2>

<ol>
  <li>Anypoint Platform 로그인 및 접근</li>
</ol>

<ul>
  <li>Runtime Manager에 접속해 애플리케이션 배포</li>
</ul>

<ol>
  <li>애플리케이션 이름 지정</li>
</ol>

<ul>
  <li>환경 내 고유 이름 설정 (3~42자, 알파벳 및 숫자 조합).</li>
</ul>

<ol>
  <li>배포 대상 선택</li>
</ol>

<ul>
  <li>서버, 서버 그룹 또는 클러스터 중 선택.</li>
</ul>

<ol>
  <li>애플리케이션 파일 업로드 방식</li>
</ol>

<ul>
  <li>Exchange에서 가져오기: 기존 애플리케이션 선택.
<img src="/assets/img/12_pub_to_ex.png" alt="alt text" />
<img src="/assets/img/13_pub_pop_up.png" alt="alt text" />
<img src="/assets/img/14_deploy_app.png" alt="alt text" />
<img src="/assets/img/15_get_from_exchange.png" alt="alt text" /></li>
  <li>ZIP 파일 업로드: 로컬파일 업로드</li>
  <li>다른 환경에서 복사: 샌드박스 등 비프로덕션 환경에서 가져오기</li>
  <li>JAR 형식 요구시: ZIP 파일의 확장자만 JAR로 변경 가능</li>
</ul>

<h2 id="13-amanypoint-monitoring-agent-설치-1">13. AM(anypoint monitoring) Agent 설치</h2>

<p><b>Azure일때</b></p>

<ol>
  <li>AzureVM 아웃바운드 포트 443 생성하여 열어 놓기
<img src="/assets/img/16_azureport.png" alt="alt text" /></li>
</ol>

<p><b>AWS일때</b></p>

<p><b>EC2 콘솔 접속 및 보안그룹으로 이동</b></p>

<ol>
  <li>AWS EC2 Console로 로그인한다.</li>
  <li>대시보드 상단 리소스 하위 인스턴스(실행중)을 클릭한다.</li>
  <li>아래 그림과 같이 첫째 인스턴스 ID를 클릭한다.</li>
  <li>둘째, 하단에 보안 탭을 클릭한다.</li>
  <li>셋째, 보안 그룹을 클릭한다.
<img src="/assets/img/26_select_security_group_aws.png" alt="alt text" /></li>
</ol>

<p><b>아웃바운드 규칙 추가</b></p>

<ol>
  <li>
    <p>인바운드 규칙 편집을 클릭
<img src="/assets/img/29_edit_outbound.png" alt="alt text" /></p>
  </li>
  <li>첫째, 규칙 추가를 클릭</li>
  <li>둘째, 아래와 같은 Spec으로 inbound 규칙 추가
    <ul>
      <li>유형: 사용자 지정 TCP</li>
      <li>포트 범위: 443</li>
      <li>CIDR 블록: 0.0.0.0/0</li>
    </ul>
  </li>
  <li>셋째, 규칙 저장 클릭
<img src="/assets/img/48_outbound443.png" alt="alt text" /></li>
</ol>

<p><b>이후 세팅</b></p>

<ol>
  <li>Anypoint Platform에서 Monitoring을 클릭하고 Settings를 누른다.
<img src="/assets/img/17_monitoring.png" alt="alt text" /></li>
  <li>MobaXterm을 사용하여 MuleSoft Root Directory에 해당페이지에서 다운받은 am.zip을 drag &amp; drop으로 옮긴다.</li>
  <li>설치파일 압축제거 및 zip파일 제거</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// rootdirectory에 압축풀기
<span class="nv">$ </span>unzip am-2.5.11.2.zip
// 압축파일 제거
<span class="nv">$ </span><span class="nb">rm</span> <span class="nt">-rf</span> am-2.5.11.2.zip
</code></pre></div></div>

<ol>
  <li>am 디렉토리로 이동 후 설치 명령어 실행</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// am 디렉토리로 이동
<span class="nv">$ </span><span class="nb">cd </span>am
// 설치 명령어 실행
<span class="nv">$ </span>./bin/install
</code></pre></div></div>

<ol>
  <li>뮬 애플리케이션을 종료하고 뮬 서버 및 뮬 애플리케이션을 다시시작한다.</li>
  <li>MobaXterm을 사용하여 am 폴더로 이동 후 아래 명령어를 입력해 설정을 한다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./bin/setup
</code></pre></div></div>

<p>참고로 뮬 서버 시작과 AM시작 명령어는 다음과 같다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Server 시작 : <span class="o">[</span>mulesoftuser@MuleSoftVM1 bin]
<span class="nv">$ </span>./<span class="nv">$MULE_HOME</span>/bin/mule start
// AM 시작 : <span class="o">[</span>mulesoftuser@MuleSoftVM1 am
<span class="nv">$ </span>./<span class="nv">$MULE_HOME</span>/am/bin/am-service start
</code></pre></div></div>

<ol>
  <li>10분이 지나면, Anypoint studio - monitoring에서 아래와 같이 확인이 가능하다.
<img src="/assets/img/18_am.png" alt="alt text" /></li>
</ol>

<h2 id="14-mulesoft-proxy-server-설치하여-reverse-proxy-적용-1">14. MuleSoft Proxy Server 설치하여 Reverse Proxy 적용</h2>

<p>상황에 따라서 MuleSoft Proxy Server를 설치하거나 Nginx를 설치하도록 하자</p>

<ol>
  <li>
    <p>(Azure 기준) 네트워크 보안 그룹에서 인바운드 80포트와 8081포트(뮬어플리케이션 listener 포트)를 열도록 인바운드 보안 규칙을 추가한다. (https 사용시 443 port도 열어야함)
<img src="/assets/img/19_80port.png" alt="alt text" /></p>
  </li>
  <li>
    <p>Proxy Server가 방화벽에 서비스를 제공해야 하는 포트를 엽니다. 예를 들어 firewalld에서 HTTP(포트 80) 및 HTTPS(포트 443)의 기본 포트를 열려면 다음을 입력합니다.</p>
  </li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>firewall-cmd <span class="nt">--permanent</span> <span class="nt">--add-port</span><span class="o">={</span>80/tcp,8081/tcp,443/tcp<span class="o">}</span>
<span class="nv">$ </span>firewall-cmd <span class="nt">--reload</span>
</code></pre></div></div>

<ol>
  <li>MobaXterm에서 서버 원격접속하여 bin으로 이동후 관리자 권한으로 뮬서버 재가동</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// MULE_HOME의 bin 디렉토리로 이동
<span class="nv">$ </span><span class="nb">cd </span>mule-enterprise-standalone-4.8.3/bin
// 관리자 권한으로 JAVA_HOME 명시하고 Mule Server 다시 시작
<span class="nv">$ </span><span class="nb">sudo </span><span class="nv">JAVA_HOME</span><span class="o">=</span><span class="nv">$JAVA_HOME</span> ./mule restart
</code></pre></div></div>

<ol>
  <li>
    <p>API Manager에서 Add new API를 클릭한다.</p>
  </li>
  <li>
    <p>Mule Runtime 설정
아래와 같이 설정한다.</p>

    <p>runtime: Mule Gateway
Proxy type: Deploy a proxy application
Target type: Hybrid
Select server: 프록시 서버 적용할 뮬 서버 선택
Next 버튼 클릭
<img src="/assets/img/20_add_api.png" alt="alt text" /></p>
  </li>
  <li>
    <p>Proxy API 설정
아래와 같이 설정한다.</p>

    <p>Create new API 선택
Name에 이름 작성
Asset type HTTP API 선택</p>
  </li>
  <li>
    <p>Downstream 설정한다.
Protocol: HTTP
Port: 80
Base path: /api (/ 로 설정하면 포트 충돌 발생함)</p>
  </li>
  <li>
    <p>Upstream 설정한다.
Upstream URL: 서버주소와 뮬어플리케이션에서 사용할 포트 조합으로 입력한다 (ex: http://20.123.45.6:8081)</p>
  </li>
  <li>
    <p>Save&amp; Deploy를 클릭하여 배포 진행한다.</p>
  </li>
  <li>
    <p>정상적으로 배포되었다면, 아래와 같이 나올 것입니다.
그 이후, 뮬 프록시 서버를 /api/개발한api주소로 호출해보자.
<img src="/assets/img/21_api_spec.png" alt="alt text" /></p>
  </li>
</ol>

<h2 id="15-필수아님-nginx-설치하여-reverse-proxy-적용-1">15. (필수아님) Nginx 설치하여 Reverse Proxy 적용</h2>

<ol>
  <li>
    <p>(Azure 기준) 네트워크 보안 그룹에서 인바운드 80포트와 8081포트를 열도록 인바운드 보안 규칙을 추가한다. (https 사용시 443 port도 열어야함)
<img src="/assets/img/19_80port.png" alt="alt text" /></p>
  </li>
  <li>
    <p>nginx 패키지를 설치합니다</p>
  </li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>yum <span class="nb">install </span>nginx
</code></pre></div></div>

<ol>
  <li>NGINX가 방화벽에 서비스를 제공해야 하는 포트를 엽니다. 예를 들어 firewalld에서 HTTP(포트 80) 및 HTTPS(포트 443)의 기본 포트를 열려면 다음을 입력합니다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>firewall-cmd <span class="nt">--permanent</span> <span class="nt">--add-port</span><span class="o">={</span>80/tcp,443/tcp,8081/tcp<span class="o">}</span>
<span class="nv">$ </span>firewall-cmd <span class="nt">--reload</span>
</code></pre></div></div>

<ol>
  <li>시스템이 부팅될 때 nginx 서비스가 자동으로 시작되도록 활성화합니다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl <span class="nb">enable </span>nginx
</code></pre></div></div>

<ol>
  <li>vi 편집기로 ngix.conf 파일 수정</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>vi /etc/nginx/nginx.conf
</code></pre></div></div>

<ol>
  <li>server &gt; location에 아래와 같이 추가 후 저장
proxy_pass의 포트는 뮬 application 마다 상이하므로 원하는 포트로 수정</li>
</ol>

<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code>   <span class="n">location</span> / {
      <span class="n">proxy_pass</span> <span class="n">http</span>://<span class="m">127</span>.<span class="m">0</span>.<span class="m">0</span>.<span class="m">1</span>:<span class="m">8081</span>; <span class="c"># 포트 8081로 요청 전달
</span>      <span class="n">proxy_set_header</span> <span class="n">Host</span> $<span class="n">host</span>;
      <span class="n">proxy_set_header</span> <span class="n">X</span>-<span class="n">Real</span>-<span class="n">IP</span> $<span class="n">remote_addr</span>;
      <span class="n">proxy_set_header</span> <span class="n">X</span>-<span class="n">Forwarded</span>-<span class="n">For</span> $<span class="n">proxy_add_x_forwarded_for</span>;
      <span class="n">proxy_set_header</span> <span class="n">X</span>-<span class="n">Forwarded</span>-<span class="n">Proto</span> $<span class="n">scheme</span>;
   }

</code></pre></div></div>

<ol>
  <li>뮬 서버 및 애플리케이션 다시 시작 후 nginx 서비스 시작</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>systemctl start nginx
</code></pre></div></div>

<ol>
  <li>정상적으로 완료 되었으면, postman에서 해당 서버 호출 시, 포트 없이 호출 가능함</li>
</ol>

<h2 id="16-필수아님-aws--azure-서버-클러스터-생성-1">16. (필수아님) AWS &amp; Azure 서버 클러스터 생성</h2>

<p>본 과정은 AWS와 Azure에 모두 기본 뮬서버 세팅이 완료된 것으로 가정한다.</p>

<h3 id="161-aws-사전-작업">16.1. AWS 사전 작업</h3>

<h4 id="1611-ec2-콘솔-접속-및-보안그룹으로-이동">16.1.1. EC2 콘솔 접속 및 보안그룹으로 이동</h4>

<ol>
  <li>AWS EC2 Console로 로그인한다.</li>
  <li>대시보드 상단 리소스 하위 인스턴스(실행중)을 클릭한다.</li>
  <li>아래 그림과 같이 첫째 인스턴스 ID를 클릭한다.</li>
  <li>둘째, 하단에 보안 탭을 클릭한다.</li>
  <li>셋째, 보안 그룹을 클릭한다.
<img src="/assets/img/26_select_security_group_aws.png" alt="alt text" /></li>
</ol>

<h4 id="1612-인바운드-규칙-추가">16.1.2. 인바운드 규칙 추가</h4>

<ol>
  <li>인바운드 규칙 편집을 클릭
<img src="/assets/img/27_edit_inbound.png" alt="alt text" /></li>
  <li>첫째, 규칙 추가를 클릭</li>
  <li>둘째, 아래와 같은 Spec으로 inbound 규칙 추가
    <ul>
      <li>유형: 사용자 지정 TCP</li>
      <li>포트 범위: 5701 - 5800</li>
      <li>CIDR 블록: 0.0.0.0/0</li>
    </ul>
  </li>
  <li>셋째, 규칙 저장 클릭
<img src="/assets/img/28_add_inbound_rule.png" alt="alt text" /></li>
</ol>

<h4 id="1613-아웃바운드-규칙-추가">16.1.3. 아웃바운드 규칙 추가</h4>

<ol>
  <li>아웃바운드 규칙 탭을 클릭하고 아웃바운드 규칙을 클릭
<img src="/assets/img/29_edit_outbound.png" alt="alt text" /></li>
  <li>첫째, 규칙 추가를 클릭</li>
  <li>둘째, 아래와 같은 Spec으로 outbound 규칙 추가
    <ul>
      <li>유형: 사용자 지정 TCP</li>
      <li>포트 범위: 5701 - 5800</li>
      <li>CIDR 블록: 0.0.0.0/0</li>
    </ul>
  </li>
  <li>셋째, 규칙 저장 클릭
<img src="/assets/img/30_add_outbound.png" alt="alt text" /></li>
</ol>

<h4 id="1614-aws-원격서버-내-방화벽-열기">16.1.4. AWS 원격서버 내 방화벽 열기</h4>

<ol>
  <li>MobaXterm으로 원격서버 접속</li>
  <li>아래 명령어를 입력하여 5701 ~ 5800번 포트까지 열기</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-port</span><span class="o">=</span>5701-5800/tcp <span class="nt">--permanent</span>
</code></pre></div></div>

<ol>
  <li>리로드하여 설정 적용</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--reload</span>
</code></pre></div></div>

<ol>
  <li>아래 명령어 입력하여 확인</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--list-ports</span>
</code></pre></div></div>

<ul>
  <li>아래와 같이 5701 - 5800이 추가되었는지 확인
<img src="/assets/img/31_ports.png" alt="alt text" /></li>
</ul>

<h3 id="162-azure-사전-작업">16.2. Azure 사전 작업</h3>

<h4 id="1621-azurevm-콘솔-접속-및-네트워크-설정으로-이동">16.2.1. AzureVM 콘솔 접속 및 네트워크 설정으로 이동</h4>

<ol>
  <li>Azure으로 로그인한다.</li>
  <li>AzureVM을 클릭하여 이동.</li>
  <li>아래 그림과 같이 첫째 네트워크 설정 클릭.</li>
  <li>둘째, 포트규칙 만들기 클릭한다.</li>
  <li>셋째, 인바운드 포트 규칙을 클릭한다.
<img src="/assets/img/32_add_inbound_rule_azure.png" alt="alt text" /></li>
</ol>

<h4 id="1622-인바운드-규칙-추가">16.2.2. 인바운드 규칙 추가</h4>

<ol>
  <li>아래 스펙대로 인바운드 규칙을 설정하고 추가를 클릭</li>
</ol>

<ul>
  <li>소스: Any</li>
  <li>원본 포트 범위: *</li>
  <li>대상 주소: Any</li>
  <li>서비스: Custom</li>
  <li>대상 포트 범위: 5701-5800</li>
  <li>프로토콜: Any</li>
  <li>작업: 허용</li>
  <li>우선순위: {우선순위는 상관없음}</li>
  <li>이름: {이름은 상관없음}
<img src="/assets/img/33_Add_Inbound_Azure.png" alt="/assets/img/33_Add_Inbound_Azure.png" /></li>
</ul>

<h4 id="1623-아웃바운드-규칙-추가">16.2.3. 아웃바운드 규칙 추가</h4>

<ol>
  <li>16.2.1. 그림을 참고하여 네트워크 설정에서 포트 규칙 만들기 클릭 후 아웃바운드 규칙을 클릭</li>
  <li>아래 스펙대로 아웃바운드 규칙을 설정하고 추가를 클릭</li>
</ol>

<ul>
  <li>소스: Any</li>
  <li>원본 포트 범위: *</li>
  <li>대상 주소: Any</li>
  <li>서비스: Custom</li>
  <li>대상 포트 범위: 5701-5800</li>
  <li>프로토콜: Any</li>
  <li>작업: 허용</li>
  <li>우선순위: {우선순위는 상관없음}</li>
  <li>이름: {이름은 상관없음}
<img src="/assets/img/34_Add_Outbound_Azure.png" alt="alt text" /></li>
</ul>

<h4 id="1624-azure-원격서버-내-방화벽-열기">16.2.4. Azure 원격서버 내 방화벽 열기</h4>

<ol>
  <li>MobaXterm으로 원격서버 접속</li>
  <li>아래 명령어를 입력하여 5701 ~ 5800번 포트까지 열기</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-port</span><span class="o">=</span>5701-5800/tcp <span class="nt">--permanent</span>
</code></pre></div></div>

<ol>
  <li>리로드하여 설정 적용</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--reload</span>
</code></pre></div></div>

<ol>
  <li>아래 명령어 입력하여 확인</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--list-ports</span>
</code></pre></div></div>

<ul>
  <li>아래와 같이 5701 - 5800이 추가되었는지 확인
<img src="/assets/img/31_ports.png" alt="alt text" /></li>
</ul>

<h3 id="163-runtime-manager에-클러스터-생성">16.3. Runtime Manager에 클러스터 생성</h3>

<h4 id="1631-클러스터-생성화면으로-이동">16.3.1. 클러스터 생성화면으로 이동</h4>

<ol>
  <li>Anypoint Platform의 Runtime Manager로 이동한다.</li>
  <li>좌측에 Servers 탭을 클릭하고 Create Cluster를 눌러 클러스터 생성화면으로 이동
<img src="/assets/img/35_Add_Cluster.png" alt="alt text" /></li>
</ol>

<h4 id="1632-클러스터-생성">16.3.2. 클러스터 생성</h4>

<ol>
  <li>아래 스팩대로 입력 후 Create Cluster를 클릭하여 클러스터 생성</li>
</ol>

<ul>
  <li>Cluster Name: {클러스터 이름은 상관없음}</li>
  <li>Cluster Type: Unicast</li>
  <li>Select Servers: AWS서버와 Azure 서버를 체크</li>
  <li>IP: Azure와 AWS의 공용 IP 주소</li>
  <li>Port: 5701
<img src="/assets/img/22_createacluster.png" alt="alt text" /></li>
</ul>

<ol>
  <li>
    <p>기존 AWS와 Azure 서버가 restart되는데까지 기다려야함 (5분정도)</p>
  </li>
  <li>
    <p>Runtime Manager Server Tab에서 Cluster status가 초록색 Running임을 확인
<img src="/assets/img/36_ConfirmCluster.png" alt="alt text" /></p>
  </li>
</ol>

<hr />

<h2 id="17-mule-gateway-with-nginx-구성">17. Mule Gateway with Nginx 구성</h2>

<h3 id="171-system-architecture-diagram">17.1. System Architecture Diagram</h3>

<p><img src="/assets/img/37_outline_mulegateway.png" alt="alt text" />
현재 챕터에서 구현할 시스템 아키텍처 다이어그램은 위 그림과 같다.</p>

<h3 id="171-aws-사전-작업">17.1. AWS 사전 작업</h3>

<h4 id="1711-ec2-콘솔-접속-및-보안그룹으로-이동">17.1.1. EC2 콘솔 접속 및 보안그룹으로 이동</h4>

<ol>
  <li>AWS EC2 Console로 로그인한다.</li>
  <li>대시보드 상단 리소스 하위 인스턴스(실행중)을 클릭한다.</li>
  <li>아래 그림과 같이 첫째 설치할 인스턴스 ID를 클릭한다.</li>
  <li>둘째, 하단에 보안 탭을 클릭한다.</li>
  <li>셋째, 보안 그룹을 클릭한다.
<img src="/assets/img/26_select_security_group_aws.png" alt="alt text" /></li>
</ol>

<h4 id="1712-인바운드-규칙-추가">17.1.2. 인바운드 규칙 추가</h4>

<ol>
  <li>인바운드 규칙 편집을 클릭
<img src="/assets/img/27_edit_inbound.png" alt="alt text" /></li>
  <li>첫째, 규칙 추가를 클릭</li>
  <li>
    <p>둘째, 아래와 같은 Spec으로 inbound 규칙 추가
80</p>

    <ul>
      <li>유형: HTTP</li>
      <li>포트 범위: 80</li>
      <li>CIDR 블록: 0.0.0.0/0</li>
    </ul>

    <p>8080</p>

    <ul>
      <li>유형: 사용자 지정 TCP</li>
      <li>포트 범위: 8080</li>
      <li>CIDR 블록: 0.0.0.0/0</li>
    </ul>

    <p>8081</p>

    <ul>
      <li>유형: 사용자 지정 TCP</li>
      <li>포트 범위: 8081</li>
      <li>CIDR 블록: 0.0.0.0/0</li>
    </ul>
  </li>
  <li>셋째, 규칙 저장 클릭
<img src="/assets/img/38_add_inbound_rule.png" alt="alt text" /></li>
</ol>

<h3 id="172-nginx-설치">17.2. Nginx 설치</h3>

<ol>
  <li>nginx 패키지를 설치합니다</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>yum <span class="nb">install </span>nginx
</code></pre></div></div>

<ol>
  <li>NGINX가 방화벽에 서비스를 제공해야 하는 포트를 엽니다. 예를 들어 firewalld에서 HTTP(포트 80) 및 HTTPS(포트 443)의 기본 포트를 열려면 다음을 입력합니다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>firewall-cmd <span class="nt">--permanent</span> <span class="nt">--add-port</span><span class="o">={</span>80/tcp,8080/tcp,8081/tcp<span class="o">}</span>
<span class="nv">$ </span>firewall-cmd <span class="nt">--reload</span>
</code></pre></div></div>

<ol>
  <li>SELinux Permissive 모드로 변경</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>setenforce 0
</code></pre></div></div>

<ol>
  <li>SELinux Permissive 모드로 변경</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>vi /etc/selinux/config
</code></pre></div></div>

<ol>
  <li>
    <p>파일 내 SELINUX=enforcing 을 SELINUX=permissive로 수정</p>
  </li>
  <li>
    <p>시스템이 부팅될 때 nginx 서비스가 자동으로 시작되도록 활성화합니다.</p>
  </li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl <span class="nb">enable </span>nginx
</code></pre></div></div>

<ol>
  <li>vi 편집기로 ngix.conf 파일 수정</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>vi /etc/nginx/nginx.conf
</code></pre></div></div>

<ol>
  <li>log_format 및 server에 아래와 같이 수정 후 저장</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c"># upstream mule-servers 설정</span>
http <span class="o">{</span>
    upstream mule-servers <span class="o">{</span>
        server 20.196.66.2:8081<span class="p">;</span>
        server 13.209.83.213:8081<span class="p">;</span>
    <span class="o">}</span>

<span class="c"># 로그 포멧 수정</span>
log_format main <span class="s1">'$remote_addr - $remote_user [$time_local] "$request" '</span>
                  <span class="s1">'upstream: $upstream_addr, '</span>
                  <span class="s1">'host: "$host", status: $status, '</span>
                  <span class="s1">'response_time: $upstream_response_time'</span><span class="p">;</span>

 <span class="c"># 서버 설정 수정:</span>
 server <span class="o">{</span>
        listen       8080<span class="p">;</span>
        listen       <span class="o">[</span>::]:8080<span class="p">;</span>
        server_name  _<span class="p">;</span>
        root         /usr/share/nginx/html<span class="p">;</span>

        <span class="c"># Load configuration files for the default server block.</span>
        include /etc/nginx/default.d/<span class="k">*</span>.conf<span class="p">;</span>

        error_page 404 /404.html<span class="p">;</span>
        location <span class="o">=</span> /404.html <span class="o">{</span>
        <span class="o">}</span>

        error_page 500 502 503 504 /50x.html<span class="p">;</span>
        location <span class="o">=</span> /50x.html <span class="o">{</span>
        <span class="o">}</span>
        <span class="c"># downstream 설정</span>
        location /api/ <span class="o">{</span>
            proxy_pass http://mule-servers/<span class="p">;</span>
            proxy_set_header Host <span class="nv">$host</span><span class="p">;</span>
            proxy_set_header X-Real-IP <span class="nv">$remote_addr</span><span class="p">;</span>
            proxy_set_header X-Forwarded-For <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
        <span class="o">}</span>
		<span class="o">}</span>
</code></pre></div></div>

<ol>
  <li>뮬 서버 및 애플리케이션 시작 후 nginx 서비스 시작</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>systemctl start nginx
</code></pre></div></div>

<h3 id="173-proxy-application-설치">17.3. Proxy Application 설치</h3>

<ol>
  <li>MuleSoft Anypoint Platform에 접속한다.</li>
</ol>

<ul>
  <li>https://anypoint.mulesoft.com/login/</li>
</ul>

<ol>
  <li>
    <p>API Manager에서 Add new API를 클릭한다.
<br /></p>
  </li>
  <li>
    <p>Mule Runtime 설정
아래와 같이 설정한다.</p>

    <p>runtime: Mule Gateway
Proxy type: Deploy a proxy application
Target type: Hybrid
Select server: 프록시 서버 적용할 뮬 서버 선택
Next 버튼 클릭
<img src="/assets/img/20_add_api.png" alt="alt text" />
<br /></p>
  </li>
  <li>
    <p>Proxy API 설정
아래와 같이 설정한다.</p>

    <p>Create new API 선택
Name에 이름 작성
Asset type HTTP API 선택
<br /></p>
  </li>
  <li>Downstream 설정한다.
Protocol: HTTP
Port: 80
Base path: /gateway
<br /></li>
  <li>Upstream 설정한다.
Upstream URL: 서버주소와 뮬어플리케이션에서 사용할 포트 조합(8080)으로 입력한다 (ex: http://20.123.45.6:8080/api)
<br /></li>
  <li>Save &amp; Deploy를 클릭하여 배포 진행한다.
<br /></li>
  <li>정상적으로 배포되었다면, 아래와 같이 나올 것입니다.
그 이후, 뮬 프록시 서버를 /gateway/개발한api주소로 호출해보자.
<img src="/assets/img/39_proxy.png" alt="alt text" /></li>
</ol>

<h2 id="18-필수아님-mule-gateway-with-elk-구성-1">18. (필수아님) Mule Gateway with ELK 구성</h2>

<h3 id="181-mule-api-gateway-wrapper-설정-변경">18.1. Mule API Gateway Wrapper 설정 변경</h3>

<ol>
  <li>wrapper.conf vi로 편집</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>vi <span class="nv">$MULE_HOME</span>/conf/wrapper.conf
</code></pre></div></div>

<ol>
  <li>wrapper.conf 설정 변경</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># &lt;n&gt;은 각 conf파일 별로 상이하기 때문에 자신의 설정파일에 알맞게 설정해야 함</span>
<span class="c"># 이미 기존 설정값이 있으면 해당 숫자(&lt;n&gt;)를 사용하고</span>
<span class="c"># 만약 없다면 가장 큰 값 + 1을 한다</span>
wrapper.java.additional.&lt;n&gt;<span class="o">=</span><span class="nt">-Danypoint</span>.platform.analytics_base_uri<span class="o">=</span>
wrapper.java.additional.&lt;n&gt;<span class="o">=</span><span class="nt">-Danypoint</span>.platform.analytics_enabled<span class="o">=</span><span class="nb">true</span>
</code></pre></div></div>

<ol>
  <li>Mule 서버 재시작</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span><span class="nv">JAVA_HOME</span><span class="o">=</span><span class="nv">$JAVA_HOME</span> ./mule restart
</code></pre></div></div>

<h3 id="182-inbound-설정-및-원격서버-포트-개방">18.2. Inbound 설정 및 원격서버 포트 개방</h3>

<p>해당 파트는 뮬소프트 로그를 전송할 ELK 서버과 어느 포트로 통신할 것인지에 따라 달라진다.
정확히는 대상 Elasticsearch와 통신할 포트에 대한 설정이다.
Elasticsearch 기본으로 9200포트로 통신함</p>

<p>아래 예제는 AWS에 선치된 Mule Gateway와 Elasticsearch가 443(https)포트로 통신하는 것을 기준으로 진행함
상황에 따라 Inbound와 Outbound를 모두 열어줘야될 수도 있음</p>

<h4 id="1821-ec2-콘솔-접속-및-보안그룹으로-이동">18.2.1. EC2 콘솔 접속 및 보안그룹으로 이동</h4>

<ol>
  <li>AWS EC2 Console로 로그인한다.</li>
  <li>대시보드 상단 리소스 하위 인스턴스(실행중)을 클릭한다.</li>
  <li>아래 그림과 같이 첫째 Mule API Gateway 인스턴스 ID를 클릭한다.</li>
  <li>둘째, 하단에 보안 탭을 클릭한다.</li>
  <li>셋째, 보안 그룹을 클릭한다.
<img src="/assets/img/26_select_security_group_aws.png" alt="alt text" /></li>
</ol>

<h4 id="1822-인바운드-규칙-추가">18.2.2. 인바운드 규칙 추가</h4>

<ol>
  <li>인바운드 규칙 편집을 클릭
<img src="/assets/img/27_edit_inbound.png" alt="alt text" /></li>
  <li>첫째, 규칙 추가를 클릭</li>
  <li>둘째, 아래와 같은 Spec으로 inbound 규칙 추가
    <ul>
      <li>유형: HTTPS</li>
      <li>포트 범위: 443</li>
      <li>CIDR 블록: 0.0.0.0/0</li>
    </ul>
  </li>
  <li>셋째, 규칙 저장 클릭</li>
</ol>

<h4 id="1823-elasticsearch와-통신할-포트-개방">18.2.3. Elasticsearch와 통신할 포트 개방</h4>

<ol>
  <li>
    <p>Mule Gateway 원격 접속한다.</p>
  </li>
  <li>
    <p>통신포트 개방 및 리로드</p>
  </li>
</ol>

<p>9200을{Elasticsearch 통신 포트}를 상황에 맞게 조정</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>firewall-cmd <span class="nt">--permanent</span> <span class="nt">--add-port</span><span class="o">={</span>9200<span class="o">}</span>/tcp<span class="o">}</span>
<span class="nv">$ </span>firewall-cmd <span class="nt">--reload</span>
</code></pre></div></div>

<h3 id="183-logstash-저장소-추가-및-설치">18.3. Logstash 저장소 추가 및 설치</h3>

<ol>
  <li>Mule Gateway EC2 SSH 접속 후 아래 명령어를 입력하여 Logstash 저장소 추가</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>rpm <span class="nt">--import</span> https://artifacts.elastic.co/GPG-KEY-elasticsearch
<span class="nb">sudo tee</span> /etc/yum.repos.d/logstash.repo <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh">
[logstash-8.x]
name=Elastic repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
</span><span class="no">EOF
</span></code></pre></div></div>

<ol>
  <li>아래 명령어를 입력하여 Logstash 설치</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># version 8.17.2으로 고정</span>
<span class="nv">$ </span><span class="nb">sudo </span>yum <span class="nb">install </span>logstash-1:8.17.2-1.x86_64 <span class="nt">-y</span>
</code></pre></div></div>

<h3 id="183-anypoint-studio-elk-연동-dateformat-설정">18.3. Anypoint Studio ELK 연동 DateFormat 설정</h3>

<p><img src="/assets/img/41_runtime_manager.png" alt="alt text" /></p>

<ol>
  <li>Anypoint Platform에서 Runtime Manager를 클릭</li>
  <li>아래 사진과 같이 Servers 클릭 후 APIGateway 클릭</li>
</ol>

<p><img src="/assets/img/42_settings.png" alt="alt text" /></p>

<ol>
  <li>Setting 탭 클릭</li>
  <li>plugins 탭 클릭</li>
  <li>톱니바퀴 클릭</li>
</ol>

<p><img src="/assets/img/43_specific_setting.png" alt="alt text" /></p>

<ol>
  <li>상단 토글을 활성화해서 상세 설정을 연다</li>
  <li>Date Format을 아래와 같이 변경한다.</li>
</ol>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yyyy-MM-dd'T'HH:mm:ss.SSSZ
</code></pre></div></div>

<ol>
  <li>Apply를 눌러 적용</li>
</ol>

<p><img src="/assets/img/44_back_to_main.png" alt="alt text" /></p>

<ol>
  <li>
    <p>Runtime Manager 페이지에서 다시 돌아간다.</p>
  </li>
  <li>
    <p>Setting 탭 클릭</p>
  </li>
  <li>
    <p>plugins 탭 클릭</p>
  </li>
  <li>
    <p>톱니바퀴 클릭</p>
  </li>
</ol>

<p><img src="/assets/img/45_gwlog.png" alt="alt text" /></p>

<ol>
  <li>
    <p>상단 토글을 활성화해서 상세 설정을 연다</p>
  </li>
  <li>
    <p>Date Format을 아래와 같이 변경한다.</p>
  </li>
</ol>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yyyy-MM-dd'T'HH:mm:ss.SSSZ
</code></pre></div></div>

<h3 id="184-log4j2-dateformat-설정">18.4. log4j2 DateFormat 설정</h3>

<ol>
  <li>서버 내 log4j2.xml 변경</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>vi <span class="nv">$MULE_HOME</span>/conf/log4j2.xml
</code></pre></div></div>

<ol>
  <li>아래 두가지 설정을 변경하여 DateFormat을 맞춤</li>
</ol>

<ul>
  <li>
    <p>Console 날짜 형식을 지정
<code class="language-plaintext highlighter-rouge">&lt;PatternLayout pattern="%-5p %d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} [%t] [processor: %X{processorPath}; event: %X{correlationId}] %c: %m%n"/&gt;</code></p>
  </li>
  <li>
    <p>ConsoleLogUtil 날짜 형식을 지정
<code class="language-plaintext highlighter-rouge">&lt;PatternLayout pattern="%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %m%n"/&gt;</code></p>
  </li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 기존</span>
&lt;?xml <span class="nv">version</span><span class="o">=</span><span class="s2">"1.0"</span> <span class="nv">encoding</span><span class="o">=</span><span class="s2">"UTF-8"</span>?&gt;
&lt;Configuration&gt;
    &lt;Appenders&gt;
        &lt;Console <span class="nv">name</span><span class="o">=</span><span class="s2">"Console"</span> <span class="nv">target</span><span class="o">=</span><span class="s2">"SYSTEM_OUT"</span><span class="o">&gt;</span>
            &lt;PatternLayout <span class="nv">pattern</span><span class="o">=</span><span class="s2">"%-5p %d [%t] [processor: %X{processorPath}; event: %X{correlationId}] %c: %m%n"</span>/&gt;
            <span class="c"># 여기 변경</span>
            &lt;PatternLayout <span class="nv">pattern</span><span class="o">=</span><span class="s2">"%-5p %d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} [%t] [processor: %X{processorPath}; event: %X{correlationId}] %c: %m%n"</span>/&gt;

        &lt;/Console&gt;
        &lt;Console <span class="nv">name</span><span class="o">=</span><span class="s2">"ConsoleLogUtil"</span> <span class="nv">target</span><span class="o">=</span><span class="s2">"SYSTEM_OUT"</span><span class="o">&gt;</span>

            &lt;PatternLayout <span class="nv">pattern</span><span class="o">=</span><span class="s2">"%m%n"</span>/&gt;
            <span class="c"># 여기 변경</span>
            &lt;PatternLayout <span class="nv">pattern</span><span class="o">=</span><span class="s2">"%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %m%n"</span>/&gt;
        &lt;/Console&gt;
    &lt;/Appenders&gt;

    &lt;Loggers&gt;

        &lt;AsyncLogger <span class="nv">name</span><span class="o">=</span><span class="s2">"org.mule.runtime.core.internal.processor.LoggerMessageProcessor"</span> <span class="nv">level</span><span class="o">=</span><span class="s2">"INFO"</span>/&gt;
        &lt;AsyncLogger <span class="nv">name</span><span class="o">=</span><span class="s2">"com.mulesoft.agent"</span> <span class="nv">level</span><span class="o">=</span><span class="s2">"INFO"</span>/&gt;

        &lt;AsyncLogger <span class="nv">name</span><span class="o">=</span><span class="s2">"org.mule.runtime.core.internal.logging"</span> <span class="nv">additivity</span><span class="o">=</span><span class="s2">"false"</span> <span class="nv">level</span><span class="o">=</span><span class="s2">"INFO"</span><span class="o">&gt;</span>
            &lt;AppenderRef <span class="nv">ref</span><span class="o">=</span><span class="s2">"ConsoleLogUtil"</span>/&gt;
        &lt;/AsyncLogger&gt;

        &lt;AsyncRoot <span class="nv">level</span><span class="o">=</span><span class="s2">"WARN"</span><span class="o">&gt;</span>
            &lt;AppenderRef <span class="nv">ref</span><span class="o">=</span><span class="s2">"Console"</span>/&gt;
        &lt;/AsyncRoot&gt;

        &lt;AsyncLogger <span class="nv">name</span><span class="o">=</span><span class="s2">"com.mulesoft.mule.runtime.gw"</span> <span class="nv">level</span><span class="o">=</span><span class="s2">"INFO"</span>/&gt;
        &lt;AsyncLogger <span class="nv">name</span><span class="o">=</span><span class="s2">"com.mulesoft.extension.policies"</span> <span class="nv">level</span><span class="o">=</span><span class="s2">"INFO"</span>/&gt;
        &lt;AsyncLogger <span class="nv">name</span><span class="o">=</span><span class="s2">"com.mulesoft.extension.gateway"</span> <span class="nv">level</span><span class="o">=</span><span class="s2">"INFO"</span>/&gt;
        &lt;AsyncLogger <span class="nv">name</span><span class="o">=</span><span class="s2">"com.mulesoft.analytics"</span> <span class="nv">level</span><span class="o">=</span><span class="s2">"INFO"</span>/&gt;

    &lt;/Loggers&gt;

&lt;/Configuration&gt;
</code></pre></div></div>

<h3 id="185-logstash-conf-파일-설정">18.5. Logstash conf 파일 설정</h3>

<ol>
  <li>Mule Gateway EC2 SSH 접속 후 mule_gateway_log.conf 생성</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>vi /etc/logstash/conf.d/mule_gateway_log.conf
</code></pre></div></div>

<ol>
  <li>mule_gateway_log.conf 작성
아래 내용을 복사해서 붙여넣기한다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>input <span class="o">{</span>
  file <span class="o">{</span>
    path <span class="o">=&gt;</span> <span class="o">[</span>
      <span class="s2">"/home/ec2-user/mule-enterprise-standalone-4.8.3/logs/events.log"</span>,
      <span class="s2">"/home/ec2-user/mule-enterprise-standalone-4.8.3/logs/gw-http-events.log"</span>
    <span class="o">]</span>
    start_position <span class="o">=&gt;</span> <span class="s2">"beginning"</span>
    sincedb_path <span class="o">=&gt;</span> <span class="s2">"/dev/null"</span>
    ignore_older <span class="o">=&gt;</span> 86400
    stat_interval <span class="o">=&gt;</span> 2
    discover_interval <span class="o">=&gt;</span> 10
    codec <span class="o">=&gt;</span> json <span class="o">{</span>
      target <span class="o">=&gt;</span> <span class="s2">"parsed_json"</span>
    <span class="o">}</span>
  <span class="o">}</span>
<span class="o">}</span>

filter <span class="o">{</span>
  <span class="c"># 원본 "message" 필드 제거 (ECS와의 충돌 방지)</span>
  mutate <span class="o">{</span>
    remove_field <span class="o">=&gt;</span> <span class="o">[</span><span class="s2">"message"</span><span class="o">]</span>
  <span class="o">}</span>

  <span class="c"># componentLocation 필드 처리: 문자열이면 Hash로 변환 후 그대로 저장</span>
  <span class="k">if</span> <span class="o">[</span>parsed_json][componentLocation] and <span class="o">[</span>parsed_json][componentLocation] <span class="o">!=</span> <span class="s2">""</span> <span class="o">{</span>
    ruby <span class="o">{</span>
      code <span class="o">=&gt;</span> <span class="s1">'
        cl = event.get("[parsed_json][componentLocation]")
        if cl.is_a?(String)
          begin
            cl = JSON.parse(cl)
          rescue JSON::ParserError
            cl = nil
          end
        end
        if cl.is_a?(Hash)
          event.set("[parsed_json][componentLocation]", cl)
        end
      '</span>
    <span class="o">}</span>
  <span class="o">}</span>

  <span class="c"># parts 배열이 존재하면, 문자열이면 Array로 변환한 후 그대로 유지</span>
  <span class="k">if</span> <span class="o">[</span>parsed_json][componentLocation][parts] and <span class="o">[</span>parsed_json][componentLocation][parts] <span class="o">!=</span> <span class="s2">""</span> <span class="o">{</span>
    ruby <span class="o">{</span>
      code <span class="o">=&gt;</span> <span class="s1">'
        parts = event.get("[parsed_json][componentLocation][parts]")
        if parts.is_a?(String)
          begin
            parts = JSON.parse(parts)
          rescue JSON::ParserError
            parts = []
          end
        end
        if parts.is_a?(Array)
          event.set("[parsed_json][componentLocation][parts]", parts)
        end
      '</span>
    <span class="o">}</span>
  <span class="o">}</span>

  <span class="c"># componentLocation 내부의 중첩 객체 처리: typedComponentIdentifier 및 partIdentifier를 객체로 저장</span>
  <span class="k">if</span> <span class="o">[</span>parsed_json][componentLocation] and <span class="o">[</span>parsed_json][componentLocation] <span class="o">!=</span> <span class="s2">""</span> <span class="o">{</span>
    ruby <span class="o">{</span>
      code <span class="o">=&gt;</span> <span class="s1">'
        fields = ["typedComponentIdentifier", "partIdentifier"]
        comp = event.get("[parsed_json][componentLocation]")
        if comp.is_a?(String)
          begin
            comp = JSON.parse(comp)
          rescue JSON::ParserError
            comp = {}
          end
        end
        if comp.is_a?(Hash) and comp["parts"].is_a?(Array)
          comp["parts"].each do |part|
            fields.each do |field|
              if part[field].is_a?(String)
                begin
                  parsed_field = JSON.parse(part[field])
                  if parsed_field.is_a?(Hash)
                    part[field] = parsed_field
                  end
                rescue JSON::ParserError
                  # 파싱 실패하면 원본 문자열 유지
                end
              end
            end
          end
          event.set("[parsed_json][componentLocation][parts]", comp["parts"])
        end
      '</span>
    <span class="o">}</span>
  <span class="o">}</span>

  <span class="c"># timestamp 변환 (밀리초 포함/미포함 모두 지원)</span>
  <span class="nb">date</span> <span class="o">{</span>
    match <span class="o">=&gt;</span> <span class="o">[</span><span class="s2">"[parsed_json][timestamp]"</span>, <span class="s2">"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</span>, <span class="s2">"yyyy-MM-dd'T'HH:mm:ssZ"</span><span class="o">]</span>
    target <span class="o">=&gt;</span> <span class="s2">"[parsed_json][timestamp]"</span>
    timezone <span class="o">=&gt;</span> <span class="s2">"UTC"</span>
  <span class="o">}</span>
<span class="o">}</span>

output <span class="o">{</span>
  elasticsearch <span class="o">{</span>
    hosts <span class="o">=&gt;</span> <span class="o">[</span><span class="s2">"https://es.fukso.dev:443"</span><span class="o">]</span>
    index <span class="o">=&gt;</span> <span class="s2">"mule-gateway-logs-%{+YYYY.MM.dd}"</span>
    user <span class="o">=&gt;</span> <span class="s2">"elastic"</span>
    password <span class="o">=&gt;</span> <span class="s2">"changeme"</span>
    ssl <span class="o">=&gt;</span> <span class="nb">true</span>
  <span class="o">}</span>
  stdout <span class="o">{</span> codec <span class="o">=&gt;</span> rubydebug <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<ol>
  <li>파일 권한 설정</li>
</ol>

<p>아래 5개 명령어를 입력하여 순차적으로 파일 권한이 설정되도록 한다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 1️⃣ /home/ec2-user/ 디렉토리를 다른 사용자(logstash)가 접근할 수 있도록 설정</span>
<span class="nb">sudo chmod </span>755 /home/ec2-user/

<span class="c"># 2️⃣ mule-enterprise-standalone-4.8.3 디렉토리를 logstash가 접근할 수 있도록 설정</span>
<span class="nb">sudo chmod </span>755 /home/ec2-user/mule-enterprise-standalone-4.8.3/

<span class="c"># 3️⃣ logs 디렉토리를 logstash가 탐색할 수 있도록 설정</span>
<span class="nb">sudo chmod </span>750 /home/ec2-user/mule-enterprise-standalone-4.8.3/logs/

<span class="c"># 4️⃣ logs 디렉토리 및 내부 파일의 소유자를 logstash로 변경</span>
<span class="nb">sudo chown</span> <span class="nt">-R</span> logstash:logstash /home/ec2-user/mule-enterprise-standalone-4.8.3/logs/

<span class="c"># 5️⃣ logstash가 로그 파일을 읽을 수 있도록 설정</span>
<span class="nb">sudo chmod </span>640 /home/ec2-user/mule-enterprise-standalone-4.8.3/logs/events.log
</code></pre></div></div>

<ol>
  <li>Logstash 실행</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl start logstash
</code></pre></div></div>

<h3 id="186-logstash-적용-및-테스트">18.6. Logstash 적용 및 테스트</h3>

<ol>
  <li>개발되어 있는 Mule Application을 호출하여 문제 없이 정상 작동하는지 확인한다.</li>
  <li>elasticsearch에서 인덱스가 생성되는지 확인</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 브라우저에서 elasticsearch의 모든 인덱스를 조회</span>
<span class="c"># 아래 사진과 같이 mule-gateway-log가 생성되면 정상 작동한 것</span>
http://<span class="o">{</span>Elasticsearch 주소<span class="o">}</span>:<span class="o">{</span>포트<span class="o">}</span>/_cat/indices?v
</code></pre></div></div>

<p><img src="/assets/img/40_indices.png" alt="alt text" /></p>

<hr />

<h2 id="19-troubleshooting-1">19. Troubleshooting</h2>

<h3 id="191-runtime-manager에서-create-cluster-failed-object-object-발생-시-해결방법">19.1. Runtime Manager에서 Create cluster failed: [object Object] 발생 시 해결방법</h3>

<p><img src="/assets/img/25_failed_cluster.png" alt="alt text" /></p>

<ol>
  <li>웹브라우저에서 오른쪽 클릭하여 검사클릭</li>
  <li>네트워크 탭에서 이름 clusters 클릭 후 응답 확인</li>
</ol>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"message": "There are applications already deployed on the following servers: [MuleSoftVM2-aws, MuleSoftVM1-azure]Please undeploy all apps from those servers before adding them to a server group."
</code></pre></div></div>

<ol>
  <li>각서버에 있는 모든 앱을 제거</li>
  <li>클러스터 재등록</li>
</ol>

<h3 id="192-am-service-status-command-not-found">19.2. am-service status: command not found</h3>

<p>“13.7.MobaXterm을 사용하여 am 폴더로 이동 후 아래 명령어를 입력해 설정을 한다.”를 진행하다가</p>

<p>am폴더에서 <code class="language-plaintext highlighter-rouge">./bin/setup</code> → <code class="language-plaintext highlighter-rouge">$MULE_HOME/am/bin/am-service start</code> 이후 아래와 같은 에러 발생</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/home/ec2-user/mule-enterprise-standalone-4.9.2/am/bin/tools/tool-rpm: line 14: /etc/rc.d/init.d/functions: No such file or directory
/home/ec2-user/mule-enterprise-standalone-4.9.2/am/bin/tools/tool-rpm: line 18: status: command not found

</code></pre></div></div>

<p>해결 방법)</p>

<p>첫 번째 에러는 시스템에 필요한 initscripts 패키지가 설치되지 않았기 때문이다. 아래 명령어로 패키지 설치할 것</p>

<ol>
  <li>패키지 설치: <code class="language-plaintext highlighter-rouge">sudo yum install initscripts</code></li>
  <li>뮬 재시작: <code class="language-plaintext highlighter-rouge">$MULE_HOME/bin/mule restart</code></li>
  <li>am폴더에서 <code class="language-plaintext highlighter-rouge">./bin/setup</code> → <code class="language-plaintext highlighter-rouge">./bin/am-service start</code></li>
</ol>

<p><img src="/assets/img/46_error-case1.png" alt="alt text" /></p>]]></content><author><name></name></author><category term="develop" /><category term="Back-End" /><category term="MuleSoft" /><summary type="html"><![CDATA[MuleSoft Hybrid 환경 구축방법에 대해 알아보자]]></summary></entry><entry><title type="html">[MuleSoft] MuleSoft FlexGateway 구축방법에 대해 알아보자</title><link href="https://billiamchoi.github.io/develop/2025/05/01/MuleSoft-FlexGateway-%EA%B5%AC%EC%B6%95-%EB%B0%A9%EB%B2%95%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90.html" rel="alternate" type="text/html" title="[MuleSoft] MuleSoft FlexGateway 구축방법에 대해 알아보자" /><published>2025-05-01T02:05:00+00:00</published><updated>2025-05-01T02:05:00+00:00</updated><id>https://billiamchoi.github.io/develop/2025/05/01/MuleSoft-FlexGateway-%EA%B5%AC%EC%B6%95-%EB%B0%A9%EB%B2%95%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</id><content type="html" xml:base="https://billiamchoi.github.io/develop/2025/05/01/MuleSoft-FlexGateway-%EA%B5%AC%EC%B6%95-%EB%B0%A9%EB%B2%95%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90.html"><![CDATA[<h1 id="mulesoft-flex-gateway-구축-manual">MuleSoft Flex Gateway 구축 Manual</h1>

<hr />

<h3 id="목차">목차</h3>

<h4 id="1-필요사항">1. 필요사항</h4>

<h4 id="2-서버-구성-및-구동">2. 서버 구성 및 구동</h4>

<h4 id="3-mobaxterm-다운로드">3. MobaXterm 다운로드</h4>

<h4 id="4-mobaxterm을-사용하여-ssh-접속">4. MobaXterm을 사용하여 SSH 접속</h4>

<h4 id="5--lvm을-이용한-home-파일-시스템-용량-확장-선택">5. 💡 LVM을 이용한 /home 파일 시스템 용량 확장 (선택)</h4>

<h4 id="6-outbound-443-port-열기">6. Outbound 443 Port 열기</h4>

<h4 id="7-flex-gateway-설치">7. Flex Gateway 설치</h4>

<h4 id="8-api-instance-설치">8. API Instance 설치</h4>

<h4 id="n-troubleshooting">n. Troubleshooting</h4>

<hr />

<h2 id="1-필요사항-1">1. 필요사항</h2>

<ul>
  <li>Azure VM</li>
  <li>Red Hat Enterprise Linux 9.4 (LVM) - x64 Gen2 (OS)</li>
  <li>MuleSoft FlexGateway 1.9.0</li>
  <li>MobaXterm</li>
</ul>

<h2 id="2-서버-구성-및-구동-1">2. 서버 구성 및 구동</h2>

<h3 id="21-azure에-설치">2.1. Azure에 설치</h3>

<p>중요 속성은 다음과 같음</p>

<ul>
  <li>초기 입력창
<img src="/assets/img/1_Azure_setting.png" alt="alt text" /></li>
</ul>

<h4 id="211-azure-중요속성">2.1.1. Azure 중요속성</h4>

<ul>
  <li>지역: Korea Central</li>
  <li>사용자이름: mulesoftuser</li>
  <li>이미지: Red Hat Enterprise Linux 9.4 (LVM) - x64 Gen2</li>
  <li>서버크기: 2 vcpu, 4 GiB 메모리</li>
</ul>

<ol>
  <li>중요속성을 준수하고 AzureVM 생성</li>
  <li>Pem Key도 중요하여 다운받는다.</li>
</ol>

<h2 id="3-mobaxterm-다운로드-1">3. MobaXterm 다운로드</h2>

<ol>
  <li>https://mobaxterm.mobatek.net/download.html 에 접속하여 Home Edition MobaXterm을 설치한다.</li>
</ol>

<h2 id="4-mobaxterm을-사용하여-ssh-접속-1">4. MobaXterm을 사용하여 SSH 접속</h2>

<ol>
  <li>
    <p>AzureVM 개요 페이지에서 연결할 공용 IP 주소를 확인한다.</p>
  </li>
  <li>
    <p>MobaXterm을 실행하여 아래와 같이 세션 설정한다.
<img src="/assets/img/2_SessionSetting.png" alt="alt text" /></p>
  </li>
</ol>

<ul>
  <li>Remote host: Azure의 공용 IP 주소 입력</li>
  <li>username: 설정한 username 입력</li>
  <li>Advenced SSH setting 탭에 Use private key 클릭 후 pem key 위치 설정</li>
</ul>

<p>위의 사항을 모두 준수하였으면 OK를 눌러 세션 설정하여 Azure VM 접속한다.</p>

<h2 id="5--lvm을-이용한-home-파일-시스템-용량-확장-선택-1">5. 💡 LVM을 이용한 /home 파일 시스템 용량 확장 (선택)</h2>

<p>다음 조건을 모두 만족하는 경우에만 본 절차를 수행하십시오:</p>

<ul class="task-list">
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />설치 대상 시스템의 운영체제가 Red Hat Enterprise Linux이며, LVM(Logical Volume Manager)을 사용 중이다.</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />원격 접속 후 df -h 명령어를 실행했을 때, /home 디렉토리의 사용 가능 용량이 설정한 저장 공간에 비해 현저히 작게 나타난다.</li>
</ul>

<h3 id="51-시스템의-운영체제-및-lvmlogical-volume-manager-확인-방법">5.1. 시스템의 운영체제 및 <strong>LVM(Logical Volume Manager)</strong> 확인 방법</h3>

<ol>
  <li>
    <p>MobaXterm으로 서버에 원격 접속한다.</p>
  </li>
  <li>
    <p>OS 확인 명령어를 입력한다.</p>
  </li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cat</span> /etc/os-release
</code></pre></div></div>

<ol>
  <li>LVM 확인 명령어를 입력한다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>lsblk
</code></pre></div></div>

<ol>
  <li>아래와 같이 PRETTY_NAME에 Red Hat Enterprise Linux가 포함되어 있고 TYPE이 lvm인지를 확인한다.
<img src="/assets/img/3_osnLvm.png" alt="alt text" /></li>
</ol>

<p>좋아요! 이어지는 <strong>용량 확장 절차</strong>를 매뉴얼 형식에 맞춰 자연스럽게 이어서 작성해드릴게요. 각 단계에 <strong>설명</strong>을 추가하여, 사용자가 왜 이 명령어를 실행하는지 쉽게 이해할 수 있도록 했습니다.</p>

<hr />

<h3 id="52-home-파일-시스템-용량-확장-절차">5.2. /home 파일 시스템 용량 확장 절차</h3>

<blockquote>
  <p>💬 <strong>사전 확인</strong>: 이 작업은 <code class="language-plaintext highlighter-rouge">/home</code> 논리 볼륨에 LVM의 남은 공간을 모두 할당하고, 해당 파일 시스템(XFS)을 확장하는 절차입니다.<br />
시스템에 따라 중요한 데이터가 있을 경우, 반드시 <strong>백업 후 진행</strong>하시기 바랍니다.</p>
</blockquote>

<h4 id="521-lvm의-남은-공간을-home-논리-볼륨에-할당">5.2.1. LVM의 남은 공간을 <code class="language-plaintext highlighter-rouge">/home</code> 논리 볼륨에 할당</h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>lvextend <span class="nt">-l</span> +100%FREE /dev/rootvg/homelv
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">-l +100%FREE</code> 옵션은 현재 Volume Group(<code class="language-plaintext highlighter-rouge">rootvg</code>) 내의 <strong>모든 남은 공간</strong>을 <code class="language-plaintext highlighter-rouge">/home</code> 논리 볼륨(<code class="language-plaintext highlighter-rouge">homelv</code>)에 할당합니다.</li>
  <li><code class="language-plaintext highlighter-rouge">/dev/rootvg/homelv</code> 경로는 시스템에 따라 다를 수 있으며, <code class="language-plaintext highlighter-rouge">lvs</code> 명령어로 확인할 수 있습니다.</li>
</ul>

<h4 id="522-파일-시스템-확장">5.2.2. 파일 시스템 확장</h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>xfs_growfs /home
</code></pre></div></div>

<ul>
  <li>LVM에 새롭게 할당된 공간이 실제 <code class="language-plaintext highlighter-rouge">/home</code> 디렉토리에서 사용 가능하도록 <strong>XFS 파일 시스템의 크기를 확장</strong>하는 명령어입니다.</li>
  <li>이 명령어는 마운트된 상태에서도 실행할 수 있으며, 시스템 재시작 없이 즉시 적용됩니다.</li>
</ul>

<h4 id="523-적용된-용량-확인">5.2.3. 적용된 용량 확인</h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">df</span> <span class="nt">-h</span> /home
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">/home</code>의 디스크 용량이 정상적으로 확장되었는지 확인합니다.</li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">Available</code> 항목에서 확장된 용량이 반영되어야 합니다.</p>

    <p><strong>참고</strong>: <code class="language-plaintext highlighter-rouge">/dev/rootvg/homelv</code>의 경로가 다른 경우, 아래 명령어로 실제 LV 이름과 마운트 위치를 먼저 확인해 주세요:</p>
  </li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">df</span> <span class="nt">-hT</span>
</code></pre></div></div>

<h2 id="6-outbound-443-port-열기-1">6. Outbound 443 Port 열기</h2>

<ol>
  <li>
    <p>AzureVM 아웃바운드 포트 443 생성하여 열어 놓기
<img src="/assets/img/4_azureport.png" alt="alt text" /></p>
  </li>
  <li>
    <p>AzureVM 내 방화벽 열기</p>
    <ul>
      <li>아래 명령어를 입력하여 443 포트 열기
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-port</span><span class="o">=</span>443/tcp <span class="nt">--permanent</span>
</code></pre></div>        </div>
      </li>
      <li>리로드하여 설정 적용
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--reload</span>
</code></pre></div>        </div>
      </li>
      <li>아래 명령어 입력하여 확인
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--list-ports</span>
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
</ol>

<h2 id="7-flex-gateway-설치-1">7. Flex Gateway 설치</h2>

<h3 id="71-gnupg2-설치">7.1. gnupg2 설치</h3>

<ol>
  <li>gnupg2 설치합니다</li>
</ol>

<ul>
  <li>다운로드 페이지
https://gnupg.org/download/index.html</li>
</ul>

<ol>
  <li>
    <p>MobaXterm으로 원격 접속합니다</p>
  </li>
  <li>
    <p>사용자 홈 디렉토리로 이동하여 다운받은 압축파일을 drag&amp;drop한다.</p>
  </li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 사용자의 홈디렉토리로 이동</span>
<span class="nv">$ </span> <span class="nb">cd</span> ~
</code></pre></div></div>

<ol>
  <li>사용자 홈 디렉토리로 이동하여 다운받은 gnpg2를 압축해제한다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 사용자의 홈디렉토리로 이동</span>
<span class="nv">$ </span><span class="nb">cd</span> ~
<span class="c"># 압축해제</span>
<span class="nv">$ </span><span class="nb">tar</span> <span class="nt">-xvjf</span> gnupg-2.4.7.tar.bz2 <span class="nt">-C</span> ~/
<span class="c"># 압축파일 삭제</span>
<span class="nv">$ </span><span class="nb">rm</span> <span class="nt">-rf</span> ./gnupg-2.4.7.tar.bz2
</code></pre></div></div>

<h3 id="721-registration-token으로-flex-gateway-설치-rhel">7.2.1. Registration token으로 Flex Gateway 설치 (RHEL)</h3>

<ol>
  <li>
    <p>MobaXterm으로 원격 접속합니다</p>
  </li>
  <li>
    <p>Flex Gateway 설치</p>
  </li>
</ol>

<ul>
  <li>버전별로 설치 스크립트가 다를 수 있으니 항상 anypoint platform 들어가서 확인한다.</li>
  <li>접속 페이지
https://anypoint.mulesoft.com/cloudhub/#/console/home/gateways/create</li>
</ul>

<p>아래 명령어를 터미널에 복사 붙여넣기해서 실행한다.</p>

<ul>
  <li>변수 $releasever는 에러가 발생하여 9로 고정하여 실행</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo tee</span> /etc/yum.repos.d/flex-gateway.repo <span class="o">&lt;&lt;</span><span class="sh">\</span><span class="no">EOF</span><span class="sh">
[flex-gateway]
name = Anypoint Flex Gateway
baseurl = https://flex-packages.anypoint.mulesoft.com/rhel/9/main
gpgcheck = 1
gpgkey = https://flex-packages.anypoint.mulesoft.com/rhel/pubkey.gpg
repo_gpgcheck = 1
enabled = 1
</span><span class="no">EOF
</span><span class="nb">sudo </span>yum <span class="nb">install</span> <span class="nt">-y</span> flex-gateway
</code></pre></div></div>

<ol>
  <li>Flex Gateway 등록</li>
</ol>

<ul>
  <li>아래는 예시일뿐 꼭 아래 링크를 방문하고, 설치할 bussinessGroup을 확인 후&lt; gateway-name&gt;를 flex gateway 이를으로 변경한다. 해당 명령어를 복사하자
    <ul>
      <li>https://anypoint.mulesoft.com/cloudhub/#/console/home/gateways/create</li>
    </ul>
  </li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> /usr/local/bin/flexctl registration create &lt;gateway-name&gt; <span class="se">\</span>
  <span class="nt">--token</span><span class="o">=</span>d573c0dd-6c36-4b55-bca4-768e2f7d85ed <span class="se">\</span>
  <span class="nt">--organization</span><span class="o">=</span>2437c48f-31ee-4850-9e15-f6942f7590eb <span class="se">\</span>
  <span class="nt">--connected</span><span class="o">=</span><span class="nb">true</span> <span class="se">\</span>
  <span class="nt">--output-directory</span><span class="o">=</span>/usr/local/share/mulesoft/flex-gateway/conf.d
</code></pre></div></div>

<ul>
  <li>참고
<img src="/assets/img/5_regiFlex.png" alt="alt text" /></li>
</ul>

<ol>
  <li>터미널에 명령어를 붙여넣기해서 실행한다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl start flex-gateway
</code></pre></div></div>

<ol>
  <li>Flex Gateway 실행</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl start flex-gateway
</code></pre></div></div>

<ol>
  <li>Flex Gateway 구동 확인</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>systemctl list-units flex-gateway.service
</code></pre></div></div>

<p>아래 화면 같이 나오면 정상 작동 한것이다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>UNIT                 LOAD   ACTIVE SUB     DESCRIPTION
flex-gateway.service loaded active running Application
</code></pre></div></div>

<h3 id="722-registration-token으로-flex-gateway-설치-ubuntu">7.2.2. Registration token으로 Flex Gateway 설치 (Ubuntu)</h3>
<ol>
  <li>
    <p>MobaXterm으로 원격 접속합니다</p>
  </li>
  <li>
    <p>Flex Gateway 설치</p>
  </li>
</ol>

<ul>
  <li>버전별로 설치 스크립트가 다를 수 있으니 항상 anypoint platform 들어가서 확인한다.</li>
  <li>접속 페이지
https://anypoint.mulesoft.com/cloudhub/#/console/home/gateways/create</li>
</ul>

<p>아래 명령어를 터미널에 복사 붙여넣기해서 실행한다.</p>

<ul>
  <li>변수 $(lsb_release -cs)는 현재 사용 중인 Ubuntu 버전의 코드명이 자동으로 치환되는데, 에러 발생 시 직접 넣어줄 것</li>
  <li>아래 코드 블럭은 docs를 참고했으나, <code class="language-plaintext highlighter-rouge">apt-key</code>의 사용은 deprecated 되었음(2025-03-27 확인)</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-XGET</span> https://flex-packages.anypoint.mulesoft.com/ubuntu/pubkey.gpg | <span class="nb">sudo </span>apt-key add -
<span class="nb">echo</span> <span class="s2">"deb [arch=amd64] https://flex-packages.anypoint.mulesoft.com/ubuntu </span><span class="si">$(</span>lsb_release <span class="nt">-cs</span><span class="si">)</span><span class="s2"> main"</span> | <span class="nb">sudo tee</span> /etc/apt/sources.list.d/mulesoft.list
<span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> flex-gateway
</code></pre></div></div>
<ul>
  <li>따라서 아래 코드 블럭을 참고할 것
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-fsSL</span> https://flex-packages.anypoint.mulesoft.com/ubuntu/pubkey.gpg | <span class="nb">sudo </span>gpg <span class="nt">--dearmor</span> <span class="nt">-o</span> /usr/share/keyrings/mulesoft-archive-keyring.gpg
<span class="nb">echo</span> <span class="s2">"deb [signed-by=/usr/share/keyrings/mulesoft-archive-keyring.gpg] https://flex-packages.anypoint.mulesoft.com/ubuntu </span><span class="si">$(</span>lsb_release <span class="nt">-cs</span><span class="si">)</span><span class="s2"> main"</span> | <span class="nb">sudo tee</span> /etc/apt/sources.list.d/mulesoft.list
<span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> flex-gateway
</code></pre></div>    </div>
    <ol>
      <li>~ 이후 등록 과정은 RHEL과 동일함</li>
    </ol>
  </li>
</ul>

<h2 id="8-api-instance-설치-1">8. API Instance 설치</h2>

<h3 id="81--api-instance-downstream을-위한-port-개방">8.1. 💡 API Instance Downstream을 위한 Port 개방</h3>

<ul>
  <li>해당 장은 프로젝트 별로 매우 상이 할 수 있습니다.</li>
  <li>Client와 API Instance가 통신할 포트를 해당장에서 개방하는 작업을 합니다.
    <ol>
      <li>AzureVM 인바운드 규칙 추가</li>
      <li>linux 서버 내 Firewall</li>
    </ol>
  </li>
</ul>

<h4 id="811-azurevm-인바운드-포트-개방">8.1.1. AzureVM 인바운드 포트 개방</h4>

<ol>
  <li>설치한 AzureVM으로 접속한다.</li>
  <li>왼쪽 탭에 네트워킹 &gt; 네트워크 설정을 선택한다.</li>
  <li>Inbound 규칙 추가한다.</li>
</ol>

<ul>
  <li>대상 포트 범위 :8081</li>
  <li>프로토콜: Any
<img src="/assets/img/9_add_inbound.png" alt="alt text" /></li>
</ul>

<h4 id="812-linux-서버에서-inbound-port-개방">8.1.2. Linux 서버에서 Inbound Port 개방</h4>

<ol>
  <li>
    <p>MobaXterm으로 서버에 원격 접속</p>
  </li>
  <li>
    <p>아래 명령어를 입력하여 8081번 포트까지 열기</p>
  </li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-port</span><span class="o">=</span>8081/tcp <span class="nt">--permanent</span>
</code></pre></div></div>

<ol>
  <li>리로드하여 설정 적용</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>firewall-cmd <span class="nt">--reload</span>
</code></pre></div></div>

<ol>
  <li>아래 명령어 입력하여 확인</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--list-ports</span>
</code></pre></div></div>

<h3 id="82-anypoint-platform에서-api-instance를-설치">8.2. Anypoint Platform에서 API Instance를 설치</h3>

<ol>
  <li>API Instance를 설치할 Flex Gateway를 선택한다.</li>
  <li>
    <p>왼쪽 APIs 탭 클릭 후, Add API 버튼 클릭한다.
<img src="/assets/img/7_API_Instance.png" alt="alt text" /></p>
  </li>
  <li>Add API에서 알맞게 선택한다.</li>
</ol>

<ul>
  <li>Select runtime: Flex Gateway</li>
  <li>Select Gateway: API Instance를 설치할 Gateway 선택</li>
</ul>

<p><img src="/assets/img/8_Add_API.png" alt="alt text" /></p>

<ol>
  <li>API이름과 Asset types를 올바르게 기입하고 Next click</li>
</ol>

<ul>
  <li>Name: 사용할 API Instance 이름</li>
  <li>Asset types: HTTP API</li>
</ul>

<p><img src="/assets/img/10_create_new_API.png" alt="alt text" /></p>

<ol>
  <li>Downstream 설정</li>
</ol>

<ul>
  <li>Protocol: HTTP</li>
  <li>Port: 8081</li>
</ul>

<p><img src="/assets/img/11_downstream.png" alt="alt text" /></p>

<ol>
  <li>Downstream 설정</li>
</ol>

<ul>
  <li>Upstream URL을 통신할 서버 수 만큼 넣어주고 Weight를 기입한다.</li>
</ul>

<p><img src="/assets/img/12_upstream.png" alt="alt text" /></p>

<ol>
  <li>정상적으로 API Instance가 배포가 되면 아래와 같이 나온다.</li>
</ol>

<p><img src="/assets/img/13_finish.png" alt="alt text" /></p>

<ol>
  <li>postman으로 해당 Instance를 호출 하여 정상 응답이 오는지 Postman으로 테스트한다.</li>
</ol>]]></content><author><name></name></author><category term="develop" /><category term="Back-End" /><category term="MuleSoft" /><summary type="html"><![CDATA[MuleSoft FlexGateway 구축방법에 대해 알아보자]]></summary></entry><entry><title type="html">Azure Terraform으로 Redhat 인프라 구축 자동화하기</title><link href="https://billiamchoi.github.io/develop/2025/04/07/azure-terraform%EC%9C%BC%EB%A1%9C-redhat-%EC%9D%B8%ED%94%84%EB%9D%BC-%EA%B5%AC%EC%B6%95-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0.html" rel="alternate" type="text/html" title="Azure Terraform으로 Redhat 인프라 구축 자동화하기" /><published>2025-04-07T00:27:00+00:00</published><updated>2025-04-07T00:27:00+00:00</updated><id>https://billiamchoi.github.io/develop/2025/04/07/azure-terraform%EC%9C%BC%EB%A1%9C-redhat-%EC%9D%B8%ED%94%84%EB%9D%BC-%EA%B5%AC%EC%B6%95-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0</id><content type="html" xml:base="https://billiamchoi.github.io/develop/2025/04/07/azure-terraform%EC%9C%BC%EB%A1%9C-redhat-%EC%9D%B8%ED%94%84%EB%9D%BC-%EA%B5%AC%EC%B6%95-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0.html"><![CDATA[<h1 id="azure-terraform">Azure Terraform</h1>

<hr />

<h3 id="목차">목차</h3>

<h4 id="1-필요사항">1. 필요사항</h4>

<h4 id="2-azure-cli-및-terraform-설치">2. Azure CLI 및 Terraform 설치</h4>

<h4 id="3-terraform-코드-구현">3. Terraform 코드 구현</h4>

<h4 id="4-terraform-초기화">4. Terraform 초기화</h4>

<h4 id="5-terraform-실행-계획-만들기">5. Terraform 실행 계획 만들기</h4>

<h4 id="6-terraform-실행-계획-적용">6. Terraform 실행 계획 적용</h4>

<h4 id="7-private-key-기반-pem-key-생성">7. private-key 기반 pem key 생성</h4>

<h4 id="8-mobaxterm을-통해-원격-서버-접속">8. MobaXterm을 통해 원격 서버 접속</h4>

<h4 id="n-references">n. References</h4>

<hr />

<h2 id="1-필요사항-1">1. 필요사항</h2>

<ul>
  <li>Azure CLI</li>
  <li>Terraform</li>
</ul>

<h2 id="2-azure-cli-및-terraform-설치-1">2. Azure CLI 및 Terraform 설치</h2>

<h3 id="21-azure-cli-설치">2.1. Azure CLI 설치</h3>

<p><a href="https://learn.microsoft.com/ko-kr/cli/azure/install-azure-cli-windows?pivots=msi">Azure CLI 다운로드 링크</a></p>

<h3 id="22-azure-cli-로그인">2.2. Azure CLI 로그인</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>az login <span class="c"># Azure CLI 로그인</span>
<span class="nv">$ </span>az account show  <span class="c"># 로그인 확인</span>
</code></pre></div></div>

<h3 id="23-chocolatey-설치-windows-용-패키지-관리자">2.3. Chocolatey 설치 (Windows 용 패키지 관리자)</h3>

<ol>
  <li>파워쉘을 실행하여 아래 명령어를 실행한다.</li>
</ol>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Set-ExecutionPolicy</span><span class="w"> </span><span class="nx">Bypass</span><span class="w"> </span><span class="nt">-Scope</span><span class="w"> </span><span class="nx">Process</span><span class="w"> </span><span class="nt">-Force</span><span class="w">
</span><span class="p">[</span><span class="n">Net.ServicePointManager</span><span class="p">]::</span><span class="n">SecurityProtocol</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="n">Net.SecurityProtocolType</span><span class="p">]::</span><span class="n">Tls12</span><span class="w">
</span><span class="nx">iex</span><span class="w"> </span><span class="p">((</span><span class="n">New-Object</span><span class="w"> </span><span class="nx">System.Net.WebClient</span><span class="p">)</span><span class="o">.</span><span class="nf">DownloadString</span><span class="p">(</span><span class="s1">'https://community.chocolatey.org/install.ps1'</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>

<h3 id="24-terraform-설치">2.4. Terraform 설치</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>choco <span class="nb">install </span>terraform
</code></pre></div></div>

<h2 id="3-terraform-코드-구현-1">3. Terraform 코드 구현</h2>

<ul>
  <li>Terraform 코드는 /terraform 위치에 정리되어 있습니다</li>
  <li>Terraform은 .tf 확장자를 가진 모든 파일을 자동으로 읽어서 하나로 합칩니다.</li>
</ul>

<ol>
  <li>Terraform 코드를 테스트할 디렉토리를 만들고, 이를 현재 디렉토리로 만듭니다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">mkdir </span>terraform
<span class="nv">$ </span><span class="nb">cd </span>terraform
</code></pre></div></div>

<h3 id="31-provider-코드-생성">3.1. provider 코드 생성</h3>

<ol>
  <li>providers.tf라는 파일을 만들고 다음 코드를 삽입합니다.</li>
</ol>

<ul>
  <li>Provider란?
    <ul>
      <li>upstream API의 logical abstraction입니다. 이들은 API 상호작용을 이해하고 resource를 노출하는 역할을 합니다.
        <ul>
          <li>클라우드 플랫폼(Azure 등)과 통신하는 방법을 알고 있습니다.</li>
          <li>Terraform 코드를 실제 API 호출로 변환합니다.</li>
          <li>Terraform이 실제 클라우드 리소스를 생성, 읽기, 업데이트 및 삭제하도록 돕습니다.</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>terraform <span class="o">{</span>
  <span class="c"># Terraform의 최소 요구 버전 설정 (0.12 이상 필요)</span>
  required_version <span class="o">=</span> <span class="s2">"&gt;=0.12"</span>

  required_providers <span class="o">{</span>
    azapi <span class="o">=</span> <span class="o">{</span>
      <span class="c"># azapi provider: Azure 리소스를 더 유연하게 제어하기 위해 사용</span>
      <span class="nb">source</span>  <span class="o">=</span> <span class="s2">"azure/azapi"</span>
      version <span class="o">=</span> <span class="s2">"~&gt;1.5"</span>  <span class="c"># 1.5버전대 사용</span>
    <span class="o">}</span>
    azurerm <span class="o">=</span> <span class="o">{</span>
      <span class="c"># azurerm provider: Azure 리소스를 관리하는 데 사용</span>
      <span class="nb">source</span>  <span class="o">=</span> <span class="s2">"hashicorp/azurerm"</span>
      version <span class="o">=</span> <span class="s2">"~&gt;3.0"</span>  <span class="c"># 3.0버전대 사용</span>
    <span class="o">}</span>
    random <span class="o">=</span> <span class="o">{</span>
      <span class="c"># random provider: 랜덤 문자열, 숫자 등을 생성할 때 사용</span>
      <span class="nb">source</span>  <span class="o">=</span> <span class="s2">"hashicorp/random"</span>
      version <span class="o">=</span> <span class="s2">"~&gt;3.0"</span>  <span class="c"># 3.0버전대 사용</span>
    <span class="o">}</span>
  <span class="o">}</span>
<span class="o">}</span>

<span class="c"># Azure 리소스를 관리하기 위한 azurerm provider 설정</span>
provider <span class="s2">"azurerm"</span> <span class="o">{</span>
  features <span class="o">{}</span>  <span class="c"># 기본 기능 활성화 (필수로 선언해야 함)</span>
<span class="o">}</span>
</code></pre></div></div>

<h3 id="32-ssh-코드-생성">3.2. ssh 코드 생성</h3>

<ol>
  <li>ssh.tf라는 파일을 만들고 다음 코드를 삽입합니다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 랜덤한 문자열을 생성하여 SSH 키 이름에 사용할 접두어로 사용</span>
resource <span class="s2">"random_pet"</span> <span class="s2">"ssh_key_name"</span> <span class="o">{</span>
  prefix    <span class="o">=</span> <span class="s2">"ssh"</span>    <span class="c"># 생성된 이름 앞에 붙을 접두어</span>
  separator <span class="o">=</span> <span class="s2">""</span>       <span class="c"># 단어들 사이에 구분자 없음 (예: sshFuzzyLion)</span>
<span class="o">}</span>

<span class="c"># Azure의 SSH Public Key 리소스를 정의 (먼저 리소스를 생성)</span>
resource <span class="s2">"azapi_resource"</span> <span class="s2">"ssh_public_key"</span> <span class="o">{</span>
  <span class="nb">type</span>      <span class="o">=</span> <span class="s2">"Microsoft.Compute/sshPublicKeys@2022-11-01"</span>  <span class="c"># 리소스 타입 및 API 버전</span>
  name      <span class="o">=</span> random_pet.ssh_key_name.id                    <span class="c"># 생성된 랜덤 이름을 사용</span>
  location  <span class="o">=</span> azurerm_resource_group.rg.location            <span class="c"># 리소스 그룹의 위치</span>
  parent_id <span class="o">=</span> azurerm_resource_group.rg.id                  <span class="c"># 소속된 리소스 그룹 ID</span>
<span class="o">}</span>

<span class="c"># 위에서 만든 SSH 키 리소스에 대해 KeyPair를 생성하는 액션 수행</span>
resource <span class="s2">"azapi_resource_action"</span> <span class="s2">"ssh_public_key_gen"</span> <span class="o">{</span>
  <span class="nb">type</span>        <span class="o">=</span> <span class="s2">"Microsoft.Compute/sshPublicKeys@2022-11-01"</span> <span class="c"># 동일한 리소스 타입</span>
  resource_id <span class="o">=</span> azapi_resource.ssh_public_key.id             <span class="c"># 대상 리소스 ID</span>
  action      <span class="o">=</span> <span class="s2">"generateKeyPair"</span>                            <span class="c"># 실행할 액션: 키 쌍 생성</span>
  method      <span class="o">=</span> <span class="s2">"POST"</span>                                       <span class="c"># HTTP 메서드 사용</span>

  response_export_values <span class="o">=</span> <span class="o">[</span><span class="s2">"publicKey"</span>, <span class="s2">"privateKey"</span><span class="o">]</span>       <span class="c"># 응답 값 중 출력할 항목 설정</span>
<span class="o">}</span>

<span class="c"># 출력 결과: 생성된 공개 키(Public Key)를 보여줌</span>
output <span class="s2">"key_data"</span> <span class="o">{</span>
  value <span class="o">=</span> azapi_resource_action.ssh_public_key_gen.output.publicKey
<span class="o">}</span>
</code></pre></div></div>

<h3 id="33-main-코드-생성">3.3. main 코드 생성</h3>

<ol>
  <li>main.tf라는 파일을 만들고 다음 코드를 삽입합니다.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 랜덤한 이름 생성을 위한 리소스 (리소스 그룹 이름에 사용할 접두어 설정)</span>
resource <span class="s2">"random_pet"</span> <span class="s2">"rg_name"</span> <span class="o">{</span>
  prefix <span class="o">=</span> var.resource_group_name_prefix
<span class="o">}</span>

<span class="c"># Azure 리소스 그룹 생성</span>
resource <span class="s2">"azurerm_resource_group"</span> <span class="s2">"rg"</span> <span class="o">{</span>
  location <span class="o">=</span> var.resource_group_location         <span class="c"># 지역 설정 (예: East US, Korea Central 등)</span>
  name     <span class="o">=</span> <span class="s2">"MuleSoftTFT"</span>                       <span class="c"># MuleSoftTFT 이름 사용</span>
<span class="o">}</span>

<span class="c"># 가상 네트워크(VNet) 생성</span>
resource <span class="s2">"azurerm_virtual_network"</span> <span class="s2">"my_terraform_network"</span> <span class="o">{</span>
  name                <span class="o">=</span> <span class="s2">"myVnet"</span>
  address_space       <span class="o">=</span> <span class="o">[</span><span class="s2">"10.0.0.0/16"</span><span class="o">]</span>           <span class="c"># VNet 주소 범위</span>
  location            <span class="o">=</span> azurerm_resource_group.rg.location
  resource_group_name <span class="o">=</span> azurerm_resource_group.rg.name
<span class="o">}</span>

<span class="c"># 서브넷 생성 (VNet 내부의 주소 블록 분할)</span>
resource <span class="s2">"azurerm_subnet"</span> <span class="s2">"my_terraform_subnet"</span> <span class="o">{</span>
  name                 <span class="o">=</span> <span class="s2">"mySubnet"</span>
  resource_group_name  <span class="o">=</span> azurerm_resource_group.rg.name
  virtual_network_name <span class="o">=</span> azurerm_virtual_network.my_terraform_network.name
  address_prefixes     <span class="o">=</span> <span class="o">[</span><span class="s2">"10.0.1.0/24"</span><span class="o">]</span>          <span class="c"># 서브넷 주소 범위</span>
<span class="o">}</span>

<span class="c"># 퍼블릭 IP 생성 (외부 인터넷과 연결될 수 있도록)</span>
resource <span class="s2">"azurerm_public_ip"</span> <span class="s2">"my_terraform_public_ip"</span> <span class="o">{</span>
  name                <span class="o">=</span> <span class="s2">"myPublicIP"</span>
  location            <span class="o">=</span> azurerm_resource_group.rg.location
  resource_group_name <span class="o">=</span> azurerm_resource_group.rg.name
  allocation_method   <span class="o">=</span> <span class="s2">"Dynamic"</span>                 <span class="c"># 동적 할당 방식</span>
<span class="o">}</span>

<span class="c"># 네트워크 보안 그룹(NSG) 생성 및 SSH 접속 허용 규칙 추가</span>
resource <span class="s2">"azurerm_network_security_group"</span> <span class="s2">"my_terraform_nsg"</span> <span class="o">{</span>
  name                <span class="o">=</span> <span class="s2">"myNetworkSecurityGroup"</span>
  location            <span class="o">=</span> azurerm_resource_group.rg.location
  resource_group_name <span class="o">=</span> azurerm_resource_group.rg.name

  security_rule <span class="o">{</span>
    name                       <span class="o">=</span> <span class="s2">"SSH"</span>           <span class="c"># 규칙 이름</span>
    priority                   <span class="o">=</span> 1001            <span class="c"># 우선순위 (낮을수록 우선)</span>
    direction                  <span class="o">=</span> <span class="s2">"Inbound"</span>       <span class="c"># 인바운드 트래픽 허용</span>
    access                     <span class="o">=</span> <span class="s2">"Allow"</span>         <span class="c"># 허용</span>
    protocol                   <span class="o">=</span> <span class="s2">"Tcp"</span>           <span class="c"># TCP 프로토콜</span>
    source_port_range          <span class="o">=</span> <span class="s2">"*"</span>             <span class="c"># 어떤 포트에서든</span>
    destination_port_range     <span class="o">=</span> <span class="s2">"22"</span>            <span class="c"># SSH 포트</span>
    source_address_prefix      <span class="o">=</span> <span class="s2">"*"</span>             <span class="c"># 어디서든</span>
    destination_address_prefix <span class="o">=</span> <span class="s2">"*"</span>             <span class="c"># 어디로든</span>
  <span class="o">}</span>
<span class="o">}</span>

<span class="c"># 네트워크 인터페이스(NIC) 생성 (VM과 네트워크 연결 역할)</span>
resource <span class="s2">"azurerm_network_interface"</span> <span class="s2">"my_terraform_nic"</span> <span class="o">{</span>
  name                <span class="o">=</span> <span class="s2">"myNIC"</span>
  location            <span class="o">=</span> azurerm_resource_group.rg.location
  resource_group_name <span class="o">=</span> azurerm_resource_group.rg.name

  ip_configuration <span class="o">{</span>
    name                          <span class="o">=</span> <span class="s2">"my_nic_configuration"</span>
    subnet_id                     <span class="o">=</span> azurerm_subnet.my_terraform_subnet.id
    private_ip_address_allocation <span class="o">=</span> <span class="s2">"Dynamic"</span>   <span class="c"># 자동 IP 할당</span>
    public_ip_address_id          <span class="o">=</span> azurerm_public_ip.my_terraform_public_ip.id
  <span class="o">}</span>
<span class="o">}</span>

<span class="c"># NIC에 NSG 연결 (보안 그룹 적용)</span>
resource <span class="s2">"azurerm_network_interface_security_group_association"</span> <span class="s2">"example"</span> <span class="o">{</span>
  network_interface_id      <span class="o">=</span> azurerm_network_interface.my_terraform_nic.id
  network_security_group_id <span class="o">=</span> azurerm_network_security_group.my_terraform_nsg.id
<span class="o">}</span>

<span class="c"># 스토리지 계정 이름의 고유성 확보를 위한 랜덤 ID 생성</span>
resource <span class="s2">"random_id"</span> <span class="s2">"random_id"</span> <span class="o">{</span>
  keepers <span class="o">=</span> <span class="o">{</span>
    resource_group <span class="o">=</span> azurerm_resource_group.rg.name  <span class="c"># 리소스 그룹이 바뀌면 새로운 ID 생성</span>
  <span class="o">}</span>
  byte_length <span class="o">=</span> 8                                     <span class="c"># 8바이트 랜덤 값</span>
<span class="o">}</span>

<span class="c"># 부팅 진단을 위한 Azure 스토리지 계정 생성</span>
resource <span class="s2">"azurerm_storage_account"</span> <span class="s2">"my_storage_account"</span> <span class="o">{</span>
  name                     <span class="o">=</span> <span class="s2">"diag</span><span class="k">${</span><span class="nv">random_id</span><span class="p">.random_id.hex</span><span class="k">}</span><span class="s2">"</span>  <span class="c"># 고유한 이름 설정</span>
  location                 <span class="o">=</span> azurerm_resource_group.rg.location
  resource_group_name      <span class="o">=</span> azurerm_resource_group.rg.name
  account_tier             <span class="o">=</span> <span class="s2">"Standard"</span>
  account_replication_type <span class="o">=</span> <span class="s2">"LRS"</span>                <span class="c"># 로컬 복제 방식</span>
<span class="o">}</span>

<span class="c"># 리눅스 가상 머신 생성</span>
resource <span class="s2">"azurerm_linux_virtual_machine"</span> <span class="s2">"my_terraform_vm"</span> <span class="o">{</span>
  name                  <span class="o">=</span> <span class="s2">"myVM"</span>
  location              <span class="o">=</span> azurerm_resource_group.rg.location
  resource_group_name   <span class="o">=</span> azurerm_resource_group.rg.name
  network_interface_ids <span class="o">=</span> <span class="o">[</span>azurerm_network_interface.my_terraform_nic.id]
  size                  <span class="o">=</span> <span class="s2">"Standard_DS1_v2"</span>        <span class="c"># VM 크기 (사양)</span>

  os_disk <span class="o">{</span>
    name                 <span class="o">=</span> <span class="s2">"myOsDisk"</span>
    caching              <span class="o">=</span> <span class="s2">"ReadWrite"</span>
    storage_account_type <span class="o">=</span> <span class="s2">"Premium_LRS"</span>          <span class="c"># 프리미엄 로컬 복제</span>
  <span class="o">}</span>

  <span class="c"># RHEL 9.4 이미지 선택</span>
  source_image_reference <span class="o">{</span>
    publisher <span class="o">=</span> <span class="s2">"redhat"</span>
    offer     <span class="o">=</span> <span class="s2">"RHEL"</span>
    sku       <span class="o">=</span> <span class="s2">"94_gen2"</span>
    version   <span class="o">=</span> <span class="s2">"9.4.2025031315"</span>  <span class="c"># 이미지 버전 (Azure Marketplace 기준)</span>
  <span class="o">}</span>

  computer_name  <span class="o">=</span> <span class="s2">"MuleSoftTFT"</span>                 <span class="c"># 가상 머신 내부에서 보일 이름</span>
  admin_username <span class="o">=</span> var.username                  <span class="c"># 관리자 사용자 이름</span>

  <span class="c"># SSH 키 기반 로그인 설정</span>
  admin_ssh_key <span class="o">{</span>
    username   <span class="o">=</span> var.username
    public_key <span class="o">=</span> azapi_resource_action.ssh_public_key_gen.output.publicKey
  <span class="o">}</span>

  <span class="c"># VM 부팅 진단 활성화</span>
  boot_diagnostics <span class="o">{</span>
    storage_account_uri <span class="o">=</span> azurerm_storage_account.my_storage_account.primary_blob_endpoint
  <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<ol>
  <li>사용할 리눅스 가상 머신 size 찾기
<a href="https://azure.microsoft.com/en-us/pricing/details/virtual-machines/linux/#pricing">Azure LinuxVM Pricing</a></li>
</ol>

<ul>
  <li>위 링크 방문하여 알맞는 Cupeter를 찾아 아래 부분을 수정한다</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 리눅스 가상 머신 생성</span>
resource <span class="s2">"azurerm_linux_virtual_machine"</span> <span class="s2">"my_terraform_vm"</span> <span class="o">{</span>
  name                  <span class="o">=</span> <span class="s2">"myVM"</span>
  location              <span class="o">=</span> azurerm_resource_group.rg.location
  resource_group_name   <span class="o">=</span> azurerm_resource_group.rg.name
  network_interface_ids <span class="o">=</span> <span class="o">[</span>azurerm_network_interface.my_terraform_nic.id]
  size                  <span class="o">=</span> <span class="s2">"Standard_DS1_v2"</span> <span class="c"># 이부분을 원하는 컴퓨터 사이즈에 맞게 수정한다.</span>
</code></pre></div></div>

<ol>
  <li>사용할 source_image reference 찾기</li>
</ol>

<ul>
  <li>아래 부분이 AzureVM에서 어떤 OS를 사용할지를 명시하는 부분이다.</li>
  <li>올바른 source image reference를 찾기 위해서는 아래 4가지를 잘 찾아야 된다.
    <ol>
      <li>publisher</li>
      <li>offer</li>
      <li>sku</li>
      <li>version</li>
    </ol>
  </li>
</ul>

<ol>
  <li>publisher 찾기</li>
</ol>

<ul>
  <li>아래 명령어를 사용하여 알맞은 publisher를 찾는다</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># location이 KoreaCentral이고 이름에 'redhat'이 들어간 pulisher 찾기</span>
<span class="nv">$ $ </span>az vm image list-publishers <span class="nt">--location</span> KoreaCentral <span class="nt">--query</span> <span class="s2">"[?contains(name, 'redhat')]"</span> <span class="nt">--output</span> table
</code></pre></div></div>

<ol>
  <li>offer 찾기</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># location이 KoreaCentral이고  publisher가 'redhat'인 offer 찾기</span>
<span class="nv">$ </span>az vm image list-offers <span class="nt">--location</span> KoreaCentral <span class="nt">--publisher</span> redhat <span class="nt">--output</span> table
</code></pre></div></div>

<ol>
  <li>sku 찾기</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#  location이 KoreaCentral이고  publisher가 'redhat'인 offer가 'RHEL'인 sku 찾기</span>
<span class="nv">$ </span>az vm image list-skus <span class="nt">--location</span> KoreaCentral <span class="nt">--publisher</span> redhat <span class="nt">--offer</span> RHEL <span class="nt">--output</span> table
</code></pre></div></div>

<ol>
  <li>image version 찾기</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># #  location이 KoreaCentral이고  publisher가 'redhat'인 offer가 'RHEL'이고 sku가 '94_gen2'인 image version 찾기</span>
<span class="nv">$ </span>az vm image list <span class="nt">--location</span> KoreaCentral <span class="nt">--publisher</span> redhat <span class="nt">--offer</span> RHEL <span class="nt">--sku</span> 94_gen2 <span class="nt">--all</span> <span class="nt">--output</span> table
</code></pre></div></div>

<ol>
  <li>main.tf 수정</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="c"># RHEL 9.4 이미지 선택</span>
  source_image_reference <span class="o">{</span>
    publisher <span class="o">=</span> <span class="s2">"redhat"</span>
    offer     <span class="o">=</span> <span class="s2">"RHEL"</span>
    sku       <span class="o">=</span> <span class="s2">"94_gen2"</span>
    version   <span class="o">=</span> <span class="s2">"9.4.2025031315"</span>  <span class="c"># 이미지 버전 (Azure Marketplace 기준)</span>
  <span class="o">}</span>
</code></pre></div></div>

<h2 id="4-terraform-초기화-1">4. Terraform 초기화</h2>

<p>Terraform init은</p>

<p>Terraform 프로젝트를 초기화하는 명령어입니다.</p>

<ul>
  <li>
    <p>필요한 Provider 다운로드</p>
  </li>
  <li>
    <p>.terraform 디렉토리 생성</p>
  </li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>terraform init <span class="nt">-upgrade</span>
</code></pre></div></div>

<h2 id="5-terraform-실행-계획-만들기-1">5. Terraform 실행 계획 만들기</h2>

<p>terraform plan -out main.tfplan은 Terraform에서 변경 계획(plan)을 파일로 저장하는 명령어입니다.</p>

<ul>
  <li>
    <p>현재 상태(state)와 .tf 코드의 차이를 비교</p>
  </li>
  <li>
    <p>무엇을 생성/수정/삭제할지 보여주는 계획(plan) 을 출력</p>
  </li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>terraform plan <span class="nt">-out</span> main.tfplan
</code></pre></div></div>

<h2 id="6-terraform-실행-계획-적용-1">6. Terraform 실행 계획 적용</h2>

<ul>
  <li>Terraform이 계획(plan) 을 기반으로 리소스를 실제로 만들거나 수정하거나 삭제하는 명령어</li>
  <li>즉, 진짜 인프라를 바꾸는 실행 단계입니다.</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>terraform apply main.tfplan
</code></pre></div></div>

<h3 id="61-실행-결과">6.1 실행 결과</h3>

<div class="language-hcl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">key_data</span> <span class="err">=</span> <span class="s2">"ssh-rsa AAAAB3Nza...generated-by-azure"</span>
<span class="nx">public_ip_address</span> <span class="err">=</span> <span class="s2">"4.230.34.8"</span>
<span class="nx">resource_group_name</span> <span class="err">=</span> <span class="s2">"MuleSoftTFT"</span>
</code></pre></div></div>

<h2 id="7-private-key-기반-pem-key-생성-1">7. private-key 기반 pem key 생성</h2>

<ul>
  <li>Terraform 상태 파일에서 SSH 개인키를 추출해서 .pem 파일로 저장하고, 권한을 설정</li>
  <li>터미널에서 아래 명령어를 실행하여 my-key.pem이라는 private key생성</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cat </span>terraform.tfstate | <span class="nb">grep</span> <span class="nt">-oP</span> <span class="s1">'(?&lt;=privateKey": ")[^"]+'</span> | <span class="nb">sed</span> <span class="s1">'s/\\r\\n/\n/g'</span> <span class="o">&gt;</span> my-key.pem <span class="o">&amp;&amp;</span> <span class="nb">chmod </span>400 my-key.pem
</code></pre></div></div>

<blockquote>
  <p>위 과정을 통해 Azure VM에 Red Hat OS 기반 서버를 성공적으로 구축할 수 있습니다.</p>
</blockquote>

<h2 id="8-mobaxterm을-통해-원격-서버-접속-1">8. MobaXterm을 통해 원격 서버 접속</h2>

<p>public_ip_address와 my-key.pem을 가지고 MobaXterm을 통해 원격 접속</p>

<h2 id="n-references-1">n. References</h2>

<ul>
  <li>https://learn.microsoft.com/ko-kr/azure/developer/terraform</li>
</ul>]]></content><author><name></name></author><category term="develop" /><category term="Back-End" /><summary type="html"><![CDATA[Azure Terraform으로 Redhat 인프라 구축 자동화하기]]></summary></entry><entry><title type="html">[MuleSoft] Message Flow를 만들어보자</title><link href="https://billiamchoi.github.io/develop/2024/11/18/mulesoft-message-flow%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90.html" rel="alternate" type="text/html" title="[MuleSoft] Message Flow를 만들어보자" /><published>2024-11-18T02:05:00+00:00</published><updated>2024-11-18T02:05:00+00:00</updated><id>https://billiamchoi.github.io/develop/2024/11/18/mulesoft-message-flow%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90</id><content type="html" xml:base="https://billiamchoi.github.io/develop/2024/11/18/mulesoft-message-flow%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90.html"><![CDATA[<h2 id="개요">개요</h2>

<h3 id="목표">목표</h3>

<ul>
  <li>MuleSoft의 Message Flow에 대해 알아보고 구현해보자</li>
</ul>

<h2 id="목차">목차</h2>

<h3 id="1-message-flow의-정의">1. Message Flow의 정의</h3>

<h3 id="2-message-flow-종류">2. Message Flow 종류</h3>

<h3 id="3-mariadb-연결">3. MariaDB 연결</h3>

<h3 id="4-message-flow-구현">4. Message Flow 구현</h3>

<hr />

<h2 id="1-message-flow의-정의-1">1. Message Flow의 정의</h2>

<p>Message Flow는 메시지가 source에서 DataWeave translation map을 거쳐 대상까지 이동하는 경로입니다.</p>

<p>시스템과 파트너 간에 메시지를 보내고 받기 위해 메시지 흐름을 설정합니다.</p>

<p><em>파트너: 외부 시스템을 의미합니다.</em></p>

<p>Message Flow는 엔드포인트, 메시지 유형, 식별자, 매핑과 같은 객체로 구성됩니다.</p>

<p>소스에서 타겟으로 비즈니스 트랜잭션 처리를 조정합니다.</p>

<p><img src="/assets/img/message-flow.png" alt="" /></p>

<h2 id="2-message-flow-종류-1">2. Message Flow 종류</h2>

<h3 id="inbound">Inbound</h3>

<p>인바운드 메시지 흐름은 파트너로부터 메시지를 수신하고</p>

<p>이를 내부 애플리케이션 메시지 형식으로 변환한 다음 변환된 메시지를 백엔드 시스템으로 전송합니다.</p>

<h3 id="outbound">Outbound</h3>

<p>아웃바운드 메시지 흐름은 백엔드 애플리케이션에서 메시지를 수신하고</p>

<p>해당 메시지를 파트너의 메시지 형식으로 변환한 다음, EDI 메시지를 파트너에게 전송합니다.</p>

<h2 id="3-mariadb-연결-1">3. MariaDB 연결</h2>

<p>Message Flow 구현에 있어 Listener, Select, Transform Message가 기본적으로 필요하다.</p>

<p>Select 컴포넌트에서 사용하는 MariaDB 연결은 MuleSoft에서 기본적으로 제공하지 않음</p>

<p>고로 커스텀 연결 Config를 생성하여 구현해야 함</p>

<h3 id="listener">Listener</h3>

<p>Message Flow의 호출을 정의하는 컴포넌트</p>

<h3 id="select">Select</h3>

<p>Database에서 조회를 하는 컴포넌트</p>

<h3 id="transform-message">Transform Message</h3>

<p>DataWeave 형식을 사용하여 Data를 변환하는 컴포넌트</p>

<p>아래는 데이터베이스 설정창이다.</p>

<p><img src="/assets/img/mariadb_connect.png" alt="" /></p>

<p>Mariadb Driver를 설치하기 위해</p>

<p>Cofigure 버튼을 눌러 Add Maven Dependency를 클릭한다.</p>

<p><img src="/assets/img/add_maven_dependency.png" alt="" /></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;dependency&gt;
	&lt;groupId&gt;org.mariadb.jdbc&lt;/groupId&gt;
	&lt;artifactId&gt;mariadb-java-client&lt;/artifactId&gt;
	&lt;version&gt;3.2.0&lt;/version&gt;
&lt;/dependency&gt;	
</code></pre></div></div>

<p>해당 mariaDB Dependency를 입력하고 Finish 버튼을 눌러 프로젝트에 설치를 합니다.</p>

<p>중요한 것은</p>

<p>URL 형식이 jdbc:mariadb:// 이고
Driver class name인 org.mariadb.jdbc.Driver 인 것이다.</p>

<h2 id="4-message-flow-구현-1">4. Message Flow 구현</h2>

<p>해당 글에서 거시적으로 접근하고자 한다.</p>

<p>아래 그림이 구현하고자 하는 .플로우이다.</p>

<p>해당 플로우에 대한 정보는 다음과 같다.</p>

<p>sourceDB의 데이터베이스이름과 테이블 이름으로 해당 테이블의 메타데이터를 조회하고</p>

<p>해당 테이블의 primary key column에 대한 메타데이터를 조회하는 flow이다.</p>

<p>해당 플로우에서는 3개의 변수를 사용한다.</p>

<ol>
  <li>데이터베이스 이름</li>
  <li>테이블 이름</li>
  <li>sourceDB에서 쿼리 결과값</li>
</ol>

<p><img src="/assets/img/custom_flow.png" alt="" /></p>

<p>아래에는 Query Metadata from sourceDB의 SQL과 input parameters이다.</p>

<p>MuleSoft에서 input parameter 변수 사용 시, SQL에서는 :변수이름으로 사용하고</p>

<p>input parameter에는 json객체로 선언하고 키는 사용할 변수명, 값에는 사용할 값을 기입한다.</p>

<p>flow 내 선언한 변수를 사용할 경우 vars.선언한 변수 이름으로 접근 가능하다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// SQL

SELECT 
    COLUMN_NAME,         
    DATA_TYPE,         
    CHARACTER_MAXIMUM_LENGTH AS MAX_LENGTH, 
    IS_NULLABLE,         
    COLUMN_KEY,           
    COLUMN_DEFAULT,      
    EXTRA                
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = :database_name  
  AND TABLE_NAME = :table_name
  AND COLUMN_KEY = 'PRI'; 

// input-parameters  

{	
  database_name: vars.database_name,
  table_name: vars.table_name
}
</code></pre></div></div>

<p>위와 같은 방법으로 flow를 구현하고 이를 테스트 한 결과는 다음과 같다.</p>

<p><img src="/assets/img/test_result.png" alt="" /></p>

<p>테스트 결과, 설정한 변수로 지정된 데이터베이스명과 테이블명에 따라, 기본 키 컬럼의 메타데이터를 조회할 수 있음을 확인하였다.</p>]]></content><author><name></name></author><category term="develop" /><category term="Back-End" /><category term="MuleSoft" /><summary type="html"><![CDATA[MuleSoft의 Message Flow에 대해 알아보고 구현해보자]]></summary></entry><entry><title type="html">About MuleSoft</title><link href="https://billiamchoi.github.io/study/2024/11/12/why-mulesoft.html" rel="alternate" type="text/html" title="About MuleSoft" /><published>2024-11-12T02:17:00+00:00</published><updated>2024-11-12T02:17:00+00:00</updated><id>https://billiamchoi.github.io/study/2024/11/12/why-mulesoft</id><content type="html" xml:base="https://billiamchoi.github.io/study/2024/11/12/why-mulesoft.html"><![CDATA[<h2 id="개요">개요</h2>

<h3 id="목표">목표</h3>

<ul>
  <li>MuleSoft의 도입 이유 및 특성에 대해 알아보자</li>
</ul>

<h2 id="목차">목차</h2>

<h3 id="1-si의-변화">1. SI의 변화</h3>

<h3 id="2-api-관리-trend">2. API 관리 Trend</h3>

<h3 id="3-full-life-cycle-api-management">3. Full Life Cycle API Management</h3>

<h3 id="4-api-led-connectivity">4. API-led Connectivity</h3>

<hr />

<h2 id="1-si의-변화-1">1. SI의 변화</h2>

<p><img src="/assets/img/si_변화.22.png" alt="" /></p>

<ul>
  <li>SI에서 개발 방법은 총 3개의 트랜드로 변화하였다.</li>
  <li>point to point 에서 ESB를 거쳐 MSA에 도달할 때 까지 API 관리의 중요성을 더 높아짐</li>
</ul>

<h2 id="2-api-관리-trend-1">2. API 관리 Trend</h2>

<ul>
  <li>다양한 유형의 API 채택으로 전사 표준화 대책 필요</li>
  <li>소비자 요구 충족을 위한 Customer Experience 강화 및 Headless Commerce API 아키텍쳐/환경 부각</li>
  <li>클라우드 전환에 따른 API를 통한 해킹 위험 부각으로 보안 거버넌스 강화 필요</li>
</ul>

<h2 id="3-full-life-cycle-api-management-1">3. Full Life Cycle API Management</h2>

<h3 id="full-life-cycle-api-management란">Full Life Cycle API Management란?</h3>

<p>API를 생성부터 폐기까지 전체 수명 주기 동안 감독하는 프로세스를 의미합니다.<br />
여기에는 API 설계, 게시, 문서화, 보안 및 분석까지 모든 것이 포함됩니다.<br />
효과적인 API 전략에는 API를 쉽게 검색하고 재사용할 수 있게 하고 적절하게 관리하고 보안을 유지하는 API 관리 솔루션이 포함되어야 합니다.</p>

<h3 id="3가지-api-라이프사이클-단계">3가지 API 라이프사이클 단계</h3>

<p><img src="/assets/img/three_life_cycle_api_management.png" alt="" /></p>

<h4 id="design">Design</h4>

<p>API 라이프사이클의 첫 번째 단계는 디자인입니다.<br />
API가 생성될 때입니다. API 디자인은 외부에서 내부로의 관점에서 시작하며, API의 “인터페이스/계약”으로 시작합니다.</p>

<p>API 개발자는 먼저 API의 “사용자 인터페이스”를 만들고 API가 어떻게 보이고 동작하는지 결정합니다.<br />
이를 API 계약이라고도 합니다.<br />
이 접근 방식은 일반적으로 “디자인 우선” 접근 방식이라고 하며 최상의 경험을 위해 최적화하기 위해 의도적인 API 디자인 라이프사이클을 따라야 합니다.<br />
이 단계는 개발자가 쉽게 이해할 수 있는 방식으로 계약을 지정하기 위해 사람이 읽을 수 있는 방식으로 수행해야 합니다.</p>

<p>이 단계에서 API 개발자는 다음 작업을 수행합니다.</p>

<p><strong>디자인</strong>: 프로세스 및 비즈니스 요구 사항 식별, 논리적 데이터 모델 생성, 논리적 서비스로 변환, API 그룹화</p>

<p><strong>시뮬레이션</strong>: 모델 API 리소스, 모델 API 작업/메서드, 모델 요청/응답 페이로드/코드</p>

<p><strong>피드백</strong>: API 모의, 대화형 콘솔 게시, 노트북 사용 사례 생성, 개발자 피드백 수신</p>

<p><strong>검증</strong>: 개발자 피드백을 기반으로 적절한 API 디자인을 수정하고 지속적으로 검증합니다.</p>

<p>잘 설계된 모든 API는 다른 API에서 반복성을 가질 것입니다. 이는 API의 구조적 수준(명사 리소스)과 메서드 수준(동사) 모두에서 모범 사례 패턴으로 쉽게 캡슐화될 수 있습니다.<br />
따라서 API 개발자가 설계 프로세스를 진행하면서 반복 가능한 패턴을 발견하고 공유할 수 있는 것이 중요합니다.</p>

<h4 id="implementation">Implementation</h4>

<p>API 구현은 차세대 기업을 가능하게 하는 데 중요한 부분입니다.<br />
수백 또는 수천 개의 API를 백엔드와 서로 연결할 수 있도록 하는 것이 핵심입니다. 이는 체계적인 방식으로 수행되어야 합니다.</p>

<p>구현 단계에는 빌드와 테스트라는 두 가지 단계가 있습니다.</p>

<p>API 개발자가 다음과 같은 아키텍처 패턴을 쉽게 사용할 수 있도록 하는 체계적인 접근 방식을 구축합니다.</p>

<ul>
  <li><strong>Orchestration</strong></li>
  <li><strong>Transformation</strong></li>
  <li><strong>Routing</strong></li>
  <li><strong>Data mapping</strong></li>
  <li><strong>Connectivity across systems</strong></li>
</ul>

<p>API가 빌드되면 예상대로 작동하는지 확인하기 위해 API 테스트를 여러 차례 거칩니다.<br />
문제 없이 테스트를 완료하면 다음 라이프사이클 단계로 넘어갈 수 있지만, 대부분의 경우 API는 배포로 넘어가기 전에 여러 차례의 테스트와 조정을 거칩니다.<br />
여기서 테스트 자동화 도구는 중요한데, 이는 지속적인 제공 및 배포의 DevOps 프로세스에 통합되기 때문입니다.</p>

<h4 id="management">Management</h4>

<p>애플리케이션 빌딩 블록이 보안 및 아키텍처 거버넌스의 모범 사례를 따르고 있는지 확인하려면 런타임에 정책을 적용하는 것이 중요합니다.<br />
API 관리자를 통해 모든 트래픽을 모니터링하는 것도 마찬가지로 중요한데, 약한 고리 하나만 있어도 배를 침몰시킬 수 있기 때문입니다.</p>

<p>이 수명 주기 단계에는 다음 단계가 있습니다.</p>

<ul>
  <li><strong>Secure</strong></li>
  <li><strong>Deploy</strong></li>
  <li><strong>Monitor</strong></li>
  <li><strong>Troubleshoot</strong></li>
  <li><strong>Manage</strong></li>
</ul>

<p>또한, 이러한 API는 다른 목적으로 재사용하기 위해 발견 가능해야 합니다.<br />
소비하는 개발자가 쉽게 찾고, 조사하고, 이해할 수 있도록 적절하게 게시할 수 있는 능력은 전체 프로그램을 만들거나 망칠 수 있습니다.</p>

<h2 id="4-api-led-connectivity-1">4. API-led Connectivity</h2>

<h3 id="api-led-connectivity란-무엇인가">API-led Connectivity란 무엇인가?</h3>

<p>API-led Connectivity는 조직의 생태계 내에서 재사용 가능하고 목적이 있는 API를 통해 데이터를 애플리케이션에 연결하는 체계적인 방법입니다.<br />
이러한 API는 시스템에서 데이터를 잠금 해제하고, 데이터를 프로세스로 구성하거나, 경험을 제공하는 특정 역할을 하도록 개발되었습니다.</p>

<p><img src="/assets/img/api-led-connectivity.png" alt="" /></p>

<h3 id="api-led-connectivity의-특징">API-led Connectivity의 특징</h3>

<h4 id="experience-api">Experience API</h4>

<ul>
  <li>Web / Mobile Application 등 End User가 직접 사용하는 Application과 연결</li>
  <li>Process 복잡함은 노출하지 않고, Application과 상호작용 할 수 있는 단순하고 일관적인 인터페이스 제공</li>
</ul>

<h4 id="process-api">Process API</h4>

<ul>
  <li>기능 Process 담당 : System API 연결하여 여러 System의 Orchestration을 통해 Process를 구현				- Process Automation으로 구현</li>
</ul>

<h4 id="system-api">System API</h4>

<ul>
  <li>Database, System 등과 직접 연결하여 Data 추출 및 관리</li>
  <li>예산 범위내 기한 준수</li>
  <li>재사용 가능</li>
  <li>변화 대비 설계</li>
  <li>거버넌스/규정준수/보안 및 확장성 고려한 구축</li>
</ul>]]></content><author><name></name></author><category term="study" /><category term="Back-End" /><category term="MuleSoft" /><summary type="html"><![CDATA[뮬소프트에 대해 알아보자]]></summary></entry><entry><title type="html">Gitlab CI CD시 npm install에서 멈춰있는 현상 해결법</title><link href="https://billiamchoi.github.io/bugs/2024/11/11/gitlab-ci-cd%EC%8B%9C-npm-install%EC%97%90%EC%84%9C-%EB%A9%88%EC%B6%B0%EC%9E%88%EB%8A%94-%ED%98%84%EC%83%81-%ED%95%B4%EA%B2%B0%EB%B2%95.html" rel="alternate" type="text/html" title="Gitlab CI CD시 npm install에서 멈춰있는 현상 해결법" /><published>2024-11-11T04:07:00+00:00</published><updated>2024-11-11T04:07:00+00:00</updated><id>https://billiamchoi.github.io/bugs/2024/11/11/gitlab-ci-cd%EC%8B%9C-npm-install%EC%97%90%EC%84%9C-%EB%A9%88%EC%B6%B0%EC%9E%88%EB%8A%94-%ED%98%84%EC%83%81-%ED%95%B4%EA%B2%B0%EB%B2%95</id><content type="html" xml:base="https://billiamchoi.github.io/bugs/2024/11/11/gitlab-ci-cd%EC%8B%9C-npm-install%EC%97%90%EC%84%9C-%EB%A9%88%EC%B6%B0%EC%9E%88%EB%8A%94-%ED%98%84%EC%83%81-%ED%95%B4%EA%B2%B0%EB%B2%95.html"><![CDATA[<h1 id="목차">목차</h1>

<h3 id="1-문제점">1. 문제점</h3>

<h3 id="2-원인-분석-및-결과">2. 원인 분석 및 결과</h3>

<h3 id="3-문제-해결">3. 문제 해결</h3>

<hr />

<h2 id="1-문제점-1">1. 문제점</h2>

<p>어느날 갑지가 원래 돌아가던 Gitlab CICD pipeline이 정상적으로 동작하지 않음</p>

<p>npm install -g @sap/cds-dk에서 계속 멈춰 있어 개발서버가 정상적으로 배포되지 않음</p>

<h2 id="2-원인-분석-및-결과-1">2. 원인 분석 및 결과</h2>

<p>문제점을 해결하기 위해 아래와 같이 기본 run 명령어에 –verbose 옵션을 추가하였다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>RUN npm install -global @sap/cds-dk --verbose
</code></pre></div></div>

<p>확인 결과, 패키지 설치에서 멈춰 있는 현상을 발견하였다.</p>

<p>그리고 10분 정도 대기해보니 아래와 같은 로그로 원인을 유추 할 수 있었다.</p>

<p><img src="/assets/img/docker_log.png" alt="" /></p>

<p>원인은 node 버전이 안 맞는 것이다.</p>

<p>고로 npm install이 정상적으로 실행되지 않았다.</p>

<h2 id="3-문제-해결-1">3. 문제 해결</h2>

<p>어디서 docker 컨테이너 내 node 버전을 설정해주는 지를 찾아야 된다.</p>

<p>.gitlab-ci.yml에서 빌드 시 사용하는 변수를 설정하는 부분이 있습니다.</p>

<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">// .gitlab-ci.yml</span>
<span class="na">variables</span><span class="pi">:</span>
  <span class="na">DOCKER_BUILDKIT</span><span class="pi">:</span> <span class="m">1</span> <span class="c1"># BuildKit 활성화</span>
  <span class="na">IMAGE_NAME</span><span class="pi">:</span> <span class="s">$NEXUS3_PRIVATE_HOST/$APP_NAME:$APP_VERSION</span>
  <span class="na">BUILD_ARG_NODE_IMAGE</span><span class="pi">:</span> <span class="s">--build-arg node_image=$ARG_NODE_IMAGE</span>
  <span class="na">BUILD_ARG_EXPOSE_PORT</span><span class="pi">:</span> <span class="s">--build-arg expose_port=$ARG_EXPOSE_PORT</span>
  <span class="na">BUILD_ARGS</span><span class="pi">:</span> <span class="s">$BUILD_ARG_NODE_IMAGE $BUILD_ARG_EXPOSE_PORT</span>

</code></pre></div></div>

<p>--build-arg를 사용하여 변수 node_image 설정합니다.</p>

<p>변수 $ARG_NODE_IMAGE는 gitlab Settings &gt; CI/CID &gt; Variables에서 설정합니다.</p>

<p>--build-arg로 node_image 변수를 build 변수로 설정하였기 때문에 아래 Dockerfile에서</p>

<p>ARG node_image로 Dockerfile 내 사용이 가능합니다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ARG node_image
ARG expose_port
FROM ${node_image}

</code></pre></div></div>

<p>변수 $ARG_NODE_IMAGE 값을 확인해보니, node:latest로 되어 있었습니다.</p>

<p>latest 태그로 배포하는 행위는 절대 하지 말아야된다는 교훈을 얻습니다.</p>

<p><strong>node:latest를 node:20.15.0으로 변경하였습니다.</strong></p>

<p><strong>노드 버전을 fix하여 문제를 해결했습니다.</strong></p>]]></content><author><name></name></author><category term="bugs" /><category term="docker" /><summary type="html"><![CDATA[Gitlab CI CD시 npm install에서 멈춰있는 현상 해결법에 대해 다룹니다.]]></summary></entry><entry><title type="html">React UI Framework 분석 및 장단점 비교</title><link href="https://billiamchoi.github.io/study/2024/11/06/react-ui-framework-%EB%B6%84%EC%84%9D-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90-%EB%B9%84%EA%B5%90.html" rel="alternate" type="text/html" title="React UI Framework 분석 및 장단점 비교" /><published>2024-11-06T06:12:00+00:00</published><updated>2024-11-06T06:12:00+00:00</updated><id>https://billiamchoi.github.io/study/2024/11/06/react-ui-framework-%EB%B6%84%EC%84%9D-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90-%EB%B9%84%EA%B5%90</id><content type="html" xml:base="https://billiamchoi.github.io/study/2024/11/06/react-ui-framework-%EB%B6%84%EC%84%9D-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90-%EB%B9%84%EA%B5%90.html"><![CDATA[<h2 id="개요">개요</h2>

<h3 id="목표">목표</h3>

<ul>
  <li>본문에서 3개 React UI Framework를 소개하고 각각의 특징점, 장단점을 비교 분석합니다.<br />
선정 기준: github star count</li>
</ul>

<h2 id="목차">목차</h2>

<h3 id="1-material-ui-mui">1. Material-UI (MUI)</h3>

<h3 id="2-ant-design">2. Ant Design</h3>

<h3 id="3-chakra-ui">3. Chakra UI</h3>

<h3 id="4-비교">4. 비교</h3>

<hr />

<h2 id="1-material-ui-mui-1">1. Material-UI (MUI)</h2>

<ul>
  <li>
    <p><strong>정의</strong></p>

    <ul>
      <li>
        <p>Material UI는 Google의 Material Design을 구현한 오픈소스 React 구성 요소 라이브러리입니다.</p>

        <ul>
          <li>
            <p>Material Design이란?</p>

            <ul>
              <li>플랫 디자인의 장점을 살리면서도 빛에 따른 종이의 그림자 효과를 이용하여 입체감을 살리는
디자인 방식</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <p><strong>특징</strong></p>

    <ul>
      <li>탬플릿 스토어가 존재하며 무료 탬플릿이 있음
링크: https://mui.com/store/</li>
      <li>
        <p>Transfer List가 존재함</p>

        <ul>
          <li>
            <p>Transtfer List란?</p>

            <ul>
              <li>
                <p>두 개의 목록 간에 아이템을 이동시킬 수 있는 UI 컴포넌트입니다</p>

                <p><img src="/assets/img/1.transfer_list.png" alt="" /></p>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <p><strong>Server-side Data handling이 안됨</strong></p>

        <ul>
          <li>
            <p>아래 4가지 항목을 무료버전에서 사용할 수 없음</p>

            <ol>
              <li>서버 측 페이징</li>
              <li>서버 측 필터링</li>
              <li>서버 측 정렬</li>
              <li>서버 측 검색</li>
            </ol>
          </li>
          <li>
            <p><strong>그러므로 무료 버전만 사용할 예정이면, Material-UI는 비추천합니다.</strong></p>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <p><strong>통계</strong></p>

    <ul>
      <li>
        <p>star count</p>

        <ul>
          <li>93.9k</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <p><strong>유료 버전</strong></p>

    <ul>
      <li>
        <p>종류</p>

        <ul>
          <li>
            <p><strong>MUI X Pro</strong></p>

            <ul>
              <li>연간 $180 또는 월 $15로, 고급 데이터 그리드와 같은 추가 컴포넌트를 제공합니다.</li>
            </ul>
          </li>
          <li>
            <p><strong>MUI X Premium</strong></p>

            <ul>
              <li>연간 $588 또는 월 $49로, Pro 버전의 모든 기능과 더불어 추가적인 고급 컴포넌트를 포함합니다.</li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <p>특징</p>

        <ul>
          <li>MUI의 고급 데이터 그리드, 차트, 날짜 및 시간 피커, 트리 뷰 같은 컴포넌트를 포함한 Pro/Enterprise 패키지를 유료로 제공합니다.</li>
          <li>특히 데이터 그리드는 대규모 데이터를 다룰 수 있는 고급 기능(가상 스크롤, 고정 열, 열 정렬 및 필터링 등)을 포함함</li>
          <li>Pro와 Enterprise 버전으로 나뉨</li>
          <li>Enterprise는 대기업에 맞춘 추가 지원 서비스와 더 많은 고급 기능을 포함하고 있음</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <p><strong>적합한 용도</strong></p>

    <ul>
      <li>현대적인 웹 애플리케이션이나 기업용 애플리케이션에 잘 어울리는 프로페셔널한 디자인</li>
    </ul>
  </li>
  <li>
    <p><strong>링크</strong></p>

    <ul>
      <li><a href="https://github.com/mui/material-ui">https://github.com/mui/material-ui</a></li>
    </ul>

    <p>​</p>
  </li>
</ul>

<h2 id="2-ant-design-1">2. Ant Design</h2>

<ul>
  <li>
    <p><strong>정의</strong></p>

    <ul>
      <li>Alibaba에서 개발한 Ant Design은 우아하고 세련된 디자인으로 유명한 UI Framework</li>
    </ul>
  </li>
  <li>
    <p><strong>특징</strong></p>

    <ul>
      <li>AntV라는 데이터 시각화 패키지 제공함</li>
    </ul>
  </li>
  <li>
    <p><strong>통계</strong></p>

    <ul>
      <li>
        <p>star count</p>

        <ul>
          <li>92.4k</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <p><strong>유료 버전</strong></p>

    <ul>
      <li>공식적인 유료 버전은 존재하지 않음
그러나 AntV의 일부 고급 시각화 도구나 플러그인은 유료 옵션에 포함 될 수 있음</li>
    </ul>
  </li>
  <li>
    <p><strong>적합한 용도</strong></p>

    <ul>
      <li>대시보드나 구조적인 레이아웃을 필요로 하는 기업용 애플리케이션.</li>
    </ul>
  </li>
  <li>
    <p><strong>링크</strong></p>

    <ul>
      <li><a href="https://github.com/ant-design/ant-design">https://github.com/ant-design/ant-design</a></li>
    </ul>
  </li>
</ul>

<h2 id="3-chakra-ui-1">3. Chakra UI</h2>

<ul>
  <li>
    <p><strong>정의</strong></p>

    <ul>
      <li>Chakra UI는 단순하고 유연하며 접근성에 중점을 둔 UI Framework</li>
    </ul>
  </li>
  <li>
    <p><strong>특징</strong></p>

    <ul>
      <li>접근성에 중점을 두고 있음</li>
      <li>스타일링을 위한 훅과 테마 및 컴포넌트 조합 기능 제공</li>
      <li>
        <p>Tree Shaking 지원</p>

        <ul>
          <li>
            <p>Tree Shaking이란?</p>

            <ul>
              <li>사용된 컴포넌트만 번들에 포함하는 행위.</li>
              <li>이로 인해 불필요한 코드가 제거되어 번들 크기가 줄어들고, 로딩 속도가 향상됨</li>
            </ul>
          </li>
        </ul>
      </li>
      <li>모듈 단위 사용 가능</li>
    </ul>
  </li>
  <li>
    <p><strong>통계</strong></p>

    <ul>
      <li>
        <p>star count</p>

        <ul>
          <li>37.8k</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <p><strong>유료 버전</strong></p>

    <ul>
      <li>
        <p>종류</p>

        <ul>
          <li>
            <p><strong>마케팅 UI</strong></p>

            <ul>
              <li>$149로, 마케팅에 특화된 UI 컴포넌트를 제공합니다.</li>
            </ul>
          </li>
          <li>
            <p><strong>애플리케이션 UI</strong></p>

            <ul>
              <li>$149로, 애플리케이션 개발에 필요한 UI 컴포넌트를 포함합니다.</li>
            </ul>
          </li>
          <li>
            <p><strong>마케팅 + 애플리케이션 UI</strong></p>

            <ul>
              <li>$249로, 위 두 가지를 모두 포함한 패키지입니다.</li>
            </ul>
          </li>
          <li>
            <p><strong>팀 라이선스</strong></p>

            <ul>
              <li>$899로, 최대 5명의 개발자가 사용할 수 있는 라이선스입니다.</li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <p>특징</p>

        <ul>
          <li>
            <p><strong>Chakra UI Pro</strong>는 Chakra UI의 유료 버전으로, 프리미엄 디자인 요소와 템플릿을 제공하여 개발자가 더 빠르게 고퀄리티의 웹 애플리케이션을 구축할 수 있도록 돕습니다.<br />
Chakra UI Pro는 다음과 같은 고급 기능과 리소스를 포함합니다</p>

            <ol>
              <li>
                <p><strong>프리미엄 컴포넌트</strong></p>

                <ul>
                  <li>일반 Chakra UI에서는 제공되지 않는 추가 컴포넌트(예: 고급 카드, 내비게이션 바, 히어로 섹션, 모달)들이 포함되어 있어 디자인과 기능을 더욱 쉽게 추가할 수 있습니다.</li>
                </ul>
              </li>
              <li>
                <p><strong>디자인 템플릿</strong></p>

                <ul>
                  <li>로그인, 회원가입, 대시보드 등 자주 사용되는 템플릿이 미리 제공되며, 이를 활용해 프로젝트의 기본 레이아웃을 빠르게 설정할 수 있습니다.</li>
                </ul>
              </li>
              <li>
                <p><strong>정기 업데이트 및 유지 보수</strong></p>

                <ul>
                  <li>유료 사용자는 Chakra 팀으로부터 정기적으로 업데이트와 개선된 기능을 받을 수 있으며, 문제 발생 시 빠른 지원을 받을 수 있습니다.</li>
                </ul>
              </li>
              <li>
                <p><strong>비즈니스 친화적인 라이선스</strong></p>

                <ul>
                  <li>Chakra UI Pro는 상업 프로젝트에서도 사용할 수 있도록 라이선스가 마련되어 있어, 기업 및 대규모 프로젝트에서도 안전하게 활용할 수 있습니다.</li>
                </ul>
              </li>
            </ol>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <p><strong>적합한 용도</strong></p>

    <ul>
      <li>접근성과 커스터마이징이 중요한 경량화된 프로젝트</li>
    </ul>
  </li>
  <li>
    <p><strong>링크</strong></p>

    <ul>
      <li><a href="https://github.com/chakra-ui/chakra-ui">https://github.com/chakra-ui/chakra-ui</a></li>
    </ul>
  </li>
</ul>

<h2 id="4-비교-1">4. 비교</h2>

<h4 id="특성별-비교">특성별 비교</h4>

<table>
  <thead>
    <tr>
      <th>특성</th>
      <th>Material-UI (MUI)</th>
      <th>Ant Design</th>
      <th>Chakra UI</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>디자인 스타일</strong></td>
      <td>Material Design 기반</td>
      <td>엔터프라이즈 지향</td>
      <td>모던하고 유연한 스타일</td>
    </tr>
    <tr>
      <td><strong>컴포넌트 다양성</strong></td>
      <td>매우 다양</td>
      <td>매우 다양</td>
      <td>제한적</td>
    </tr>
    <tr>
      <td><strong>커스터마이징</strong></td>
      <td>중간 정도 (약간 복잡)</td>
      <td>약간 어려움</td>
      <td>매우 유연함</td>
    </tr>
    <tr>
      <td><strong>국제화 지원</strong></td>
      <td>제한적</td>
      <td>매우 강력</td>
      <td>제한적</td>
    </tr>
    <tr>
      <td><strong>접근성</strong></td>
      <td>기본 제공</td>
      <td>기본 제공</td>
      <td>매우 우수</td>
    </tr>
    <tr>
      <td><strong>성능</strong></td>
      <td>중간 정도 (크기 조정 필요)</td>
      <td>중간 정도 (크기 조정 필요)</td>
      <td>경량화 (성능 우수)</td>
    </tr>
    <tr>
      <td><strong>커뮤니티와 지원</strong></td>
      <td>매우 활발</td>
      <td>매우 활발</td>
      <td>상대적으로 적음</td>
    </tr>
  </tbody>
</table>

<h4 id="장단점-비교">장단점 비교</h4>

<table>
  <thead>
    <tr>
      <th>Framework</th>
      <th>장점</th>
      <th>단점</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Material-UI</strong></td>
      <td>- 구글 Material Design 기반<br />- 다양한 컴포넌트 제공<br />- 테마 커스터마이징 용이<br />- 강력한 커뮤니티와 문서화</td>
      <td>- 복잡한 커스터마이징<br />- 제한된 디자인 유연성<br />- 번들 크기 큼 <br />- 핵심 기능이 유료</td>
    </tr>
    <tr>
      <td><strong>Ant Design</strong></td>
      <td>- 엔터프라이즈 애플리케이션에 최적<br />- 데이터 중심 컴포넌트 강점<br />- 국제화(i18n) 지원<br />- 디자인 언어 기반 커스터마이징 용이</td>
      <td>- 스타일 변경 어려움<br />- 디자인 통일성으로 유연성 제한<br />- 번들 크기 큼</td>
    </tr>
    <tr>
      <td><strong>Chakra UI</strong></td>
      <td>- 모던하고 유연한 스타일<br />- 경량화된 컴포넌트로 성능 우수<br />- 테마 기반 손쉬운 커스터마이징<br />- 높은 접근성 제공</td>
      <td>- 제한된 컴포넌트<br />- 상대적으로 작은 커뮤니티<br />- 엔터프라이즈 기능 부족</td>
    </tr>
  </tbody>
</table>]]></content><author><name></name></author><category term="study" /><category term="Front-End" /><summary type="html"><![CDATA[React 유명 UI Framework 분석 및 장단점 비교]]></summary></entry><entry><title type="html">[클린코드] 4장. 주석</title><link href="https://billiamchoi.github.io/study/2024/11/05/%ED%81%B4%EB%A6%B0%EC%BD%94%EB%93%9C-4%EC%9E%A5-%EC%A3%BC%EC%84%9D.html" rel="alternate" type="text/html" title="[클린코드] 4장. 주석" /><published>2024-11-05T07:00:00+00:00</published><updated>2024-11-05T07:00:00+00:00</updated><id>https://billiamchoi.github.io/study/2024/11/05/%ED%81%B4%EB%A6%B0%EC%BD%94%EB%93%9C-4%EC%9E%A5-%EC%A3%BC%EC%84%9D</id><content type="html" xml:base="https://billiamchoi.github.io/study/2024/11/05/%ED%81%B4%EB%A6%B0%EC%BD%94%EB%93%9C-4%EC%9E%A5-%EC%A3%BC%EC%84%9D.html"><![CDATA[<h1 id="목차">목차</h1>

<h3 id="1-주석">1. 주석</h3>

<h3 id="2-좋은-주석">2. 좋은 주석</h3>

<h3 id="3-나쁜-주석">3. 나쁜 주석</h3>

<hr />

<h2 id="1-주석-1">1. 주석</h2>

<ul>
  <li>필요악으로 표현</li>
  <li>코드로 의도를 표현하지 못해, 실패를 만회하기 위해 주석을 사용함</li>
  <li>주석이 필요한 상황에 처하면 곰곰히 생각할 것</li>
  <li>현실적으로 코드와 주석을 모두 유지보수하는 것은 어렵기 때문에 주석에 대한 좋은 인식이 없음</li>
  <li>
    <p>코드로 의도를 표현해라</p>

    <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="c1">// 전</span>
 <span class="c1">// 직원에게 복지 혜택을 받을 자격이 있는지 검사한다.</span>
 <span class="k">if</span> <span class="p">((</span><span class="nx">employee</span><span class="p">.</span><span class="nx">flags</span> <span class="o">&amp;</span> <span class="nx">HOURLY_FLAG</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="nx">employee</span><span class="p">.</span><span class="nx">age</span> <span class="o">&gt;</span> <span class="mi">65</span><span class="p">))</span>

 <span class="c1">// 후</span>
 <span class="k">if</span> <span class="p">(</span><span class="nx">employee</span><span class="p">.</span><span class="nx">isEligibleForFullBenefits</span><span class="p">())</span>
</code></pre></div>    </div>
  </li>
</ul>

<h2 id="2-좋은-주석-1">2. 좋은 주석</h2>

<ul>
  <li>법적인 주석
    <ul>
      <li>각 소스 파일 첫머리에 추가한 표준 주석 헤더</li>
    </ul>
  </li>
  <li>정보를 제공하는 주석
    <ul>
      <li>기본적은 정보를 제공함
  ex) 추상 메서드가 반환할 값을 설명</li>
    </ul>
  </li>
  <li>의도를 설명하는 주석
    <ul>
      <li>때때로 주석은 결정에 깔린 의도까지 설명함</li>
    </ul>
  </li>
  <li>의미를 명료하게 밝히는 주석
    <ul>
      <li>때때로 모호한 인수나 반환값은 그 의미를 읽기 좋게 표현하면 이해하기 쉬워짐</li>
    </ul>
  </li>
  <li>결과를 경고하는 주석
    <ul>
      <li>프로그래머에게 경고를 할 목적으로 사용하는 주석</li>
    </ul>
  </li>
  <li>TODO 주석
    <ul>
      <li>앞으로 할 일을 남기는 주석</li>
    </ul>
  </li>
  <li>중요성을 강조하는 주석
    <ul>
      <li>자칫 대수롭지 않다고 여겨질 무언가의 중요성을 강조하기 위해서 주석을 사용</li>
    </ul>
  </li>
</ul>

<h2 id="2-나쁜-주석">2. 나쁜 주석</h2>

<ul>
  <li>주절거리는 주석</li>
  <li>같은 이야기를 중복하는 주석</li>
  <li>오해할 여지가 있는 주석</li>
  <li>의무적으로 다는 주석</li>
  <li>이력을 기록하는 주석</li>
  <li>있으나 마나 한 주석</li>
  <li>위치를 표시하는 주석</li>
  <li>닫는 괄호에 다는 주석</li>
  <li>공로를 돌리거나 저자를 표시하는 주석</li>
  <li>주석으로 처리한 코드</li>
  <li>HTML 주석
    <ul>
      <li>pre tag나 기타 html 태그를 사용</li>
      <li>필자도 한때 pre를 사용해서 indentation을 적용해본 기억이 있음</li>
    </ul>
  </li>
  <li>전역 정보</li>
  <li>너무 많은 정보</li>
  <li>모호한 관계</li>
  <li>함수 헤더</li>
</ul>]]></content><author><name></name></author><category term="study" /><category term="Java" /><summary type="html"><![CDATA[주석에 대해 알아보자]]></summary></entry><entry><title type="html">Docker 컨테이너로 배포 시, 외부통신이 느릴 경우 해결 방법</title><link href="https://billiamchoi.github.io/bugs/2024/11/05/docker-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%A1%9C-%EB%B0%B0%ED%8F%AC-%EC%8B%9C-%EC%99%B8%EB%B6%80%ED%86%B5%EC%8B%A0%EC%9D%B4-%EB%8A%90%EB%A6%B4-%EA%B2%BD%EC%9A%B0-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95.html" rel="alternate" type="text/html" title="Docker 컨테이너로 배포 시, 외부통신이 느릴 경우 해결 방법" /><published>2024-11-05T04:24:00+00:00</published><updated>2024-11-05T04:24:00+00:00</updated><id>https://billiamchoi.github.io/bugs/2024/11/05/docker-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%A1%9C-%EB%B0%B0%ED%8F%AC-%EC%8B%9C-%EC%99%B8%EB%B6%80%ED%86%B5%EC%8B%A0%EC%9D%B4-%EB%8A%90%EB%A6%B4-%EA%B2%BD%EC%9A%B0-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95</id><content type="html" xml:base="https://billiamchoi.github.io/bugs/2024/11/05/docker-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%A1%9C-%EB%B0%B0%ED%8F%AC-%EC%8B%9C-%EC%99%B8%EB%B6%80%ED%86%B5%EC%8B%A0%EC%9D%B4-%EB%8A%90%EB%A6%B4-%EA%B2%BD%EC%9A%B0-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95.html"><![CDATA[<h1 id="목차">목차</h1>

<h3 id="1-문제점">1. 문제점</h3>

<h3 id="2-원인-분석-및-결과">2. 원인 분석 및 결과</h3>

<h3 id="3-문제-해결">3. 문제 해결</h3>

<h3 id="4-google-공용-dns">4. Google 공용 DNS</h3>

<hr />

<h2 id="1-문제점-1">1. 문제점</h2>

<ul>
  <li>
    <p>개발서버에 배포 시, 로그인 처리가 느린 현상</p>

    <ul>
      <li>로그인 시 사용하는 URL: http://login.microsoft.com</li>
    </ul>
  </li>
</ul>

<h2 id="2-원인-분석-및-결과-1">2. 원인 분석 및 결과</h2>

<ul>
  <li>ping 명령어를 사용해서 로컬에서 먼저 http://login.microsoft.com를 확인함</li>
  <li>
    <p>docker 컨테이너 내부에 들어가서 ping을 날려봄</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># docker 컨테이너 접속</span>
<span class="nv">$docker</span> <span class="nb">exec</span> <span class="nt">-it</span> &lt;컨테이너_id&gt; /bin/bash

<span class="c"># ping 설치</span>
<span class="nv">$apt</span> update
<span class="nv">$apt</span> <span class="nb">install </span>iputils-ping

<span class="c"># ping 날리기</span>
<span class="nv">$ping</span> login.microsoft.com
</code></pre></div>    </div>
  </li>
  <li>분석 결과, 도커 컨테이너 내부에서 핑이 느리게 옴</li>
</ul>

<h2 id="3-문제-해결-1">3. 문제 해결</h2>

<ul>
  <li>
    <p>docker run 명령어에 dns 옵션 추가</p>

    <div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># --dns 플래그를 docker run에 적용</span>
<span class="pi">-</span> <span class="s">docker run -d --dns 8.8.8.8 --name $APP_NAME --restart=always -p  $ARG_EXPOSE_PORT:$ARG_EXPOSE_PORT -e PORT=$ARG_EXPOSE_PORT $IMAGE_NAME</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p>docker로 배포 후 /etc/resolv.conf 파일 확인</p>

    <ul>
      <li>
        <p>수정 전</p>

        <p><img src="/assets/img/before_resolv.conf.png" alt="" /></p>
      </li>
      <li>
        <p>수정 후</p>

        <p><img src="/assets/img/resolvconf.png" alt="" /></p>
      </li>
    </ul>
  </li>
</ul>

<p>수정하고 확인 해보니 문제가 해결됨</p>

<h2 id="4-google-공용-dns-1">4. Google 공용 DNS</h2>

<h3 id="정의">정의</h3>
<p>DNS 8.8.8.8은 구글에서 제공하는 공용 DNS 서버 주소로, 누구나 무료로 사용할 수 있는 DNS 서비스</p>

<h3 id="장점">장점</h3>

<ul>
  <li>
    <p>빠른 응답 속도<br />
구글의 DNS 서버는 전 세계에 분산되어 있어 빠른 속도로 도메인 이름을 IP 주소로 변환할 수 있습니다. 특히, 일부 ISP가 제공하는 기본 DNS보다 응답 속도가 빠를 수 있음</p>
  </li>
  <li>
    <p>안정성<br />
구글은 대규모 서버 네트워크와 고성능 인프라를 운영하기 때문에, 공용 DNS 서버의 안정성과 가용성이 매우 높습니다. 서버 다운타임이 거의 없어 연결 문제가 줄어들 가능성이 큼</p>
  </li>
  <li>
    <p>보안 강화<br />
구글 DNS는 DNSSEC를 지원하여 보안을 강화합니다. 이는 악의적인 DNS 스푸핑 공격을 방지하는 데 도움을 주며, 사용자가 안전하게 웹사이트에 접속할 수 있음</p>
  </li>
  <li>
    <p>필터링 없는 접근<br />
특정 지역의 ISP에서는 일부 웹사이트를 필터링하거나 제한할 수 있지만, 구글 DNS를 사용하면 이러한 제한을 우회할 가능성이 높아질 수 있음</p>
  </li>
  <li>
    <p>투명성<br />
구글의 DNS는 로깅 정책이 명확하며, 많은 사용자들이 이미 사용하고 있어 신뢰할 수 있는 서비스</p>
  </li>
  <li>
    <p>개선된 연결성<br />
특정 ISP의 DNS가 느리거나 불안정한 경우, 구글의 DNS로 전환하면 더 나은 웹사이트 연결성을 경험할 수 있음</p>
  </li>
</ul>]]></content><author><name></name></author><category term="bugs" /><category term="docker" /><summary type="html"><![CDATA[Docker 컨테이너 베포 시, 외부통신이 느릴 경우 해결 방법에 대해 알아봅니다.]]></summary></entry><entry><title type="html">SAP UI5로 CMS 구축기</title><link href="https://billiamchoi.github.io/develop/2024/11/01/sap-ui5%EB%A1%9C-cms-%EA%B5%AC%EC%B6%95%EA%B8%B0.html" rel="alternate" type="text/html" title="SAP UI5로 CMS 구축기" /><published>2024-11-01T08:25:00+00:00</published><updated>2024-11-01T08:25:00+00:00</updated><id>https://billiamchoi.github.io/develop/2024/11/01/sap-ui5%EB%A1%9C-cms-%EA%B5%AC%EC%B6%95%EA%B8%B0</id><content type="html" xml:base="https://billiamchoi.github.io/develop/2024/11/01/sap-ui5%EB%A1%9C-cms-%EA%B5%AC%EC%B6%95%EA%B8%B0.html"><![CDATA[<h1 id="목차">목차</h1>

<h3 id="1-개요">1. 개요</h3>

<h3 id="2-역할">2. 역할</h3>

<h3 id="3-배운-것-learned">3. 배운 것 (Learned)</h3>

<h3 id="4-놀랐던-것-longed-for">4. 놀랐던 것 (Longed-for)</h3>

<h3 id="5-부족했던-것-lacked">5. 부족했던 것 (Lacked)</h3>

<hr />

<h2 id="1-개요-1">1. 개요</h2>

<h3 id="11-화면-개요">1.1. 화면 개요</h3>

<p><img src="/assets/img/ui5_sitemap.png" alt="" /></p>

<h3 id="12-erd">1.2. ERD</h3>

<p><img src="/assets/img/cms_dev-public.png" alt="" /></p>

<h3 id="13-기술-스택">1.3. 기술 스택</h3>

<ul>
  <li>SAPUI5 3.11</li>
  <li>CAP 7.9.3</li>
  <li>PostgreSQL 15.2</li>
</ul>

<h3 id="14-개념-정리">1.4. 개념 정리</h3>

<h4 id="cap이란">CAP이란?</h4>

<ul>
  <li>실시간 협업을 위한 구축하기 위한 언어 , 라이브러리 및 도구 의 개발 프레임워크</li>
  <li>약자: SAP Cloud Application Programming Model </li>
</ul>

<h4 id="cds이란">CDS이란?</h4>

<ul>
  <li>SAP HANA 데이터베이스에서 데이터 모델링을 간편하게 수행하기 위한 언어 및 
개발 프레임워크</li>
  <li>약자: Core Data Services</li>
</ul>

<h3 id="sapui5이란">SAPUI5이란?</h3>

<ul>
  <li>SAP에서 제공하는 JavaScript기반 UI 개발 프레임워크</li>
</ul>

<h2 id="2-역할-1">2. 역할</h2>

<ul>
  <li>공통 컴포넌트를 사용하여 CMS 화면 개발</li>
</ul>

<h2 id="3-배운-것-learned-1">3. 배운 것 (Learned)</h2>

<ul>
  <li>JavaScript에서 Null 판별 함수 사용법</li>
  <li>공통 컴포넌트 개발 경험</li>
  <li>cds에서는 코드에서 연결 관계를 맺어줬으나, database상에 적용은 되지 않음 (외래키)</li>
  <li>cds에서 엔티티 속성 변경이 발생하면 모든 테이블을 드랍하고 다시 만들어야됨</li>
  <li>
    <p>백엔드에서 오는 메세지를 코드 별로 정리하여 프론트에서도 메세지 처리</p>

    <ul>
      <li>백엔드의 코드 별 메세지와 프론트의 코드 별 메세지가 다름</li>
    </ul>
  </li>
</ul>

<h2 id="4-놀랐던-것-longed-for-1">4. 놀랐던 것 (Longed-for)</h2>

<ul>
  <li>개발 서버 배포 시, 로그인 처리만 느리게 되는 현상을 찾고 해결한 과정
    <ul>
      <li>네임서버 관련 이슈였는데 이는 추후 포스팅으로 별도 다룰 예정</li>
    </ul>
  </li>
</ul>

<h2 id="5-부족했던-것-lacked-1">5. 부족했던 것 (Lacked)</h2>

<ul>
  <li>변화되는 요구사항에 따른 화면 개발 속도</li>
</ul>]]></content><author><name></name></author><category term="develop" /><category term="SAPUI5" /><summary type="html"><![CDATA[UI5로 CMS 구축 회고록]]></summary></entry></feed>