<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>귤까먹는 코끼리 개발자</title>
    <link>https://elephant-dev.tistory.com/</link>
    <description>
</description>
    <language>ko</language>
    <pubDate>Sun, 21 Jun 2026 07:31:16 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>코끼리 개발자</managingEditor>
    <image>
      <title>귤까먹는 코끼리 개발자</title>
      <url>https://tistory1.daumcdn.net/tistory/5167770/attach/fcdd0a66c028483c902ed8673232835b</url>
      <link>https://elephant-dev.tistory.com</link>
    </image>
    <item>
      <title>[Linux] 메모리 누수 위치 찾기 (valgrind, 발그린드)</title>
      <link>https://elephant-dev.tistory.com/46</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발을 마무리 할 때, 메모리 누수가 없는 지 확인하는 작업은 필수적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 정리한 메모리 증가 확인 방법에 대한 포스팅을 꽤나 많은 사람들이 참조하고 있다.&lt;/p&gt;
&lt;figure id=&quot;og_1724128975182&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Linux] 메모리 증가 확인 방법(pmap, ps, /proc/pid/status )&quot; data-og-description=&quot;리눅스 환경에서 특정 프로세스의 메모리가 증가하는지 확인하는 방법 입니다.C언어를 이용해서 모듈을 만들고 프로세스를 모니터링 할 때 메모리 누수가 있는지 확인할 때 사용했던 방법입니&quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/15&quot; data-og-url=&quot;https://elephant-dev.tistory.com/15&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/wnun0/hyWOp3OUe8/XYIdzmYWgJr50L9noLxHzK/img.png?width=441&amp;amp;height=21&amp;amp;face=0_0_441_21,https://scrap.kakaocdn.net/dn/brQNuD/hyWOmst5Dr/2zwfxDAUoNjnGrAVEMHJ81/img.png?width=441&amp;amp;height=21&amp;amp;face=0_0_441_21,https://scrap.kakaocdn.net/dn/SGXJe/hyWSohTiy0/xoWmsJgunma8FuEaJTHx21/img.png?width=753&amp;amp;height=655&amp;amp;face=0_0_753_655&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/15&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/15&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/wnun0/hyWOp3OUe8/XYIdzmYWgJr50L9noLxHzK/img.png?width=441&amp;amp;height=21&amp;amp;face=0_0_441_21,https://scrap.kakaocdn.net/dn/brQNuD/hyWOmst5Dr/2zwfxDAUoNjnGrAVEMHJ81/img.png?width=441&amp;amp;height=21&amp;amp;face=0_0_441_21,https://scrap.kakaocdn.net/dn/SGXJe/hyWSohTiy0/xoWmsJgunma8FuEaJTHx21/img.png?width=753&amp;amp;height=655&amp;amp;face=0_0_753_655');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Linux] 메모리 증가 확인 방법(pmap, ps, /proc/pid/status )&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;리눅스 환경에서 특정 프로세스의 메모리가 증가하는지 확인하는 방법 입니다.C언어를 이용해서 모듈을 만들고 프로세스를 모니터링 할 때 메모리 누수가 있는지 확인할 때 사용했던 방법입니&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에는 간단히 메모리 누수가 있는지 모니터링 해보았다고하면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 누수가 발생하고 있는 소스코드 위치를 파악할 수 있는 동적 분석 툴 valgrind를 이용한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 누수 위치 찾기 포스팅을 진행해 보려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, valgrind가 사용하고자 하는 linux에 존재하는지 확인한 후 없다면 설치를 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(valgrind --version 커맨드 입력 시 버전 정보 출력되지 않는 다면 설치를 진행하자.)&lt;/p&gt;
&lt;pre id=&quot;code_1724129203948&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ yum install valgrind&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 바로 사용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;valgrind의 명령어 기본 형식은 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724130044229&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;valgrind [options] [program] [program arguments]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;u&gt;&lt;i&gt;[options]&lt;/i&gt;&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;--leak-check=&amp;lt;yes|no|summary|full&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;메모리 누수 검사를 활성화 하는 옵션&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;no : 메모리 누수 검사를 하지 않음&lt;/li&gt;
&lt;li&gt;summary: 메모리 누수에 대한 요약만 출력&lt;/li&gt;
&lt;li&gt;full: 누수된 메모리 블록에 대한 모든 세부 정보 출력&lt;/li&gt;
&lt;li&gt;yes: summay와 동일&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; --log-file=&amp;lt;file&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;valgrind가 생성하는 로그를 지정된 파일로 저장&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;--log-file=out.log 로 지정하면, out.log 파일에 로그를 저장함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; -v 또는 --verbose&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;valgrind가 더 자세한 출력을 하며, valgrind가 수행하는 작업에 대한 세부 정보 제공&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;--error-limit=&amp;lt;yes|no&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;발생하는 오류의 수에 대한 제한 설정&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;no로 설정하면 오류 수에 제한을 두지 않고, 모든 오류를 출력&lt;/li&gt;
&lt;li&gt;기본값은 yes이며, 오류 수가 많다면 일부만 출력하고 나머지는 생략할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt; --track-origins=&amp;lt;yes|no&amp;gt; &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;초기화 되지 않은 메모리에 접근하는 오류 발생 시, 해당 메모리가 어디서 부터 유래했는지 추적&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;기본값은 no이며, yes로 설정하면 메모리 사용 오류의 원인을 추적하는데 도움이 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; --show-reachable=&amp;lt;yes|no&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;프로그램 종료 시 접근 가능한 메모리에 대한 정보를 출력할지 여부를 결정&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;기본값은 no이며, yes로 설정하면 아직 접근 가능한(해제되지 않은) 메모리 블록을 보여줌&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; --child-silent-after-fork=&amp;lt;yes|no&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;프로그램이 fork()를 호출한 후 자식 프로세스의 valgrind 출력을 억제할지 여부 결정&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;기본값은 yes&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; --tool=&amp;lt;toolname&amp;gt; &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;사용할 valgrind 도구 지정. memcheck를 기본 도구로 사용함.&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;다른 도구로는 callgrind(프로파일링), cachegrind(캐시 사용 분석), massif(힙 메모리 사용 분석) 등이 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; --num-callers=&amp;lt;number&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;오류가 발생했을 때 보고할 호출 스택의 깊이 지정&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;--trace-children=&amp;lt;yes|no&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;자식 프로세스도 함께 추적할지 여부 설정&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;기본값은 no이며, yes로 설정하면 자식 프로세스에서도 메모리 오류를 추적&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;i&gt;[Program]&lt;/i&gt;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석 할 실행파일의 경로 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;i&gt;[Program arguments]&lt;/i&gt;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 파일에 전달할 인자들&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 누수가 발생하도록 간단한 프로그램을 짜서 확인해보도록 해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 malloc_free 함수에서는 free를 잘 해주고, malloc_leak 함수에선 할당한 메모리를 해제하지 않고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지속적으로 1초마다 누수를 발생시키도록 test.c 코드를 짜보았다.&lt;/p&gt;
&lt;pre id=&quot;code_1724130845315&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include&amp;lt;stdio.h&amp;gt;
#include&amp;lt;stdlib.h&amp;gt;



void malloc_free()
{
        char *good = NULL;
        good = (char *)malloc(sizeof(char )*100000000);

        free(good);
}

void malloc_leak()
{
        char *bad = NULL;
        bad = (char *)malloc(sizeof(char )*100000000);

        //free(bad); // 메모리 해제 주석

}

void main()
{
        while(1)
        {
                malloc_free();
                malloc_leak();
                sleep(1);
        }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 빌드를 해주고, valgrind를 통해 누수를 찾아보자.&lt;/p&gt;
&lt;pre id=&quot;code_1724130845317&quot; class=&quot;cmake&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;gcc -o test test.c&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음, --leak-check=full,&amp;nbsp; --log-file=mem.log -v(verbose를 통한 자세한 출력), --error-limit=no 옵션을 사용해서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누수된 메모리 블록에 대한 세부 정보를 확인하고, 해당 내용을 로그로 남겨보도록 해볼 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1724131011579&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;valgrind --leak-check=full --log-file=mem.log -v --error-limit=no ./test&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 ctrl+c 로 인터럽트를 걸어 실행을 멈춘 후 mem.log를 확인해보면 다음과 같다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;==121593==&amp;nbsp;Memcheck,&amp;nbsp;a&amp;nbsp;memory&amp;nbsp;error&amp;nbsp;detector &lt;br /&gt;==121593==&amp;nbsp;Copyright&amp;nbsp;(C)&amp;nbsp;2002-2017,&amp;nbsp;and&amp;nbsp;GNU&amp;nbsp;GPL'd,&amp;nbsp;by&amp;nbsp;Julian&amp;nbsp;Seward&amp;nbsp;et&amp;nbsp;al. &lt;br /&gt;==121593==&amp;nbsp;Using&amp;nbsp;Valgrind-3.15.0-608cb11914-20190413&amp;nbsp;and&amp;nbsp;LibVEX;&amp;nbsp;rerun&amp;nbsp;with&amp;nbsp;-h&amp;nbsp;for&amp;nbsp;copyright&amp;nbsp;info &lt;br /&gt;==121593==&amp;nbsp;Command:&amp;nbsp;./test &lt;br /&gt;==121593==&amp;nbsp;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;Parent&amp;nbsp;PID:&amp;nbsp;112655&lt;/span&gt; &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;--121593--&amp;nbsp; &lt;br /&gt;--121593--&amp;nbsp;Valgrind&amp;nbsp;options: &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--leak-check=full &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--log-file=mem.log &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-v &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--error-limit=no &lt;br /&gt;--121593--&amp;nbsp;Contents&amp;nbsp;of&amp;nbsp;/proc/version: &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;Linux&amp;nbsp;version&amp;nbsp;3.10.0-1160.119.1.el7.x86_64&amp;nbsp;(mockbuild@kbuilder.bsys.centos.org)&amp;nbsp;(gcc&amp;nbsp;version&amp;nbsp;4.8.5&amp;nbsp;20150623&amp;nbsp;(Red&amp;nbsp;Hat&amp;nbsp;4.8.5-44)&amp;nbsp;(GCC)&amp;nbsp;)&amp;nbsp;#1&amp;nbsp;SMP&amp;nbsp;Tue&amp;nbsp;Jun&amp;nbsp;4&amp;nbsp;14:43:51&amp;nbsp;UTC&amp;nbsp;2024 &lt;br /&gt;--121593--&amp;nbsp; &lt;br /&gt;--121593--&amp;nbsp;Arch&amp;nbsp;and&amp;nbsp;hwcaps:&amp;nbsp;AMD64,&amp;nbsp;LittleEndian,&amp;nbsp;amd64-cx16-lzcnt-rdtscp-sse3-ssse3-avx-avx2-bmi-f16c-rdrand &lt;br /&gt;--121593--&amp;nbsp;Page&amp;nbsp;sizes:&amp;nbsp;currently&amp;nbsp;4096,&amp;nbsp;max&amp;nbsp;supported&amp;nbsp;4096 &lt;br /&gt;--121593--&amp;nbsp;Valgrind&amp;nbsp;library&amp;nbsp;directory:&amp;nbsp;/usr/libexec/valgrind &lt;br /&gt;--121593-- Reading syms from /home/test/test &lt;br /&gt;--121593--&amp;nbsp;Reading&amp;nbsp;syms&amp;nbsp;from&amp;nbsp;/usr/lib64/ld-2.17.so &lt;br /&gt;--121593--&amp;nbsp;Reading&amp;nbsp;syms&amp;nbsp;from&amp;nbsp;/usr/libexec/valgrind/memcheck-amd64-linux &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;object&amp;nbsp;doesn't&amp;nbsp;have&amp;nbsp;a&amp;nbsp;symbol&amp;nbsp;table &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;object&amp;nbsp;doesn't&amp;nbsp;have&amp;nbsp;a&amp;nbsp;dynamic&amp;nbsp;symbol&amp;nbsp;table &lt;br /&gt;--121593--&amp;nbsp;Scheduler:&amp;nbsp;using&amp;nbsp;generic&amp;nbsp;scheduler&amp;nbsp;lock&amp;nbsp;implementation. &lt;br /&gt;--121593--&amp;nbsp;Reading&amp;nbsp;suppressions&amp;nbsp;file:&amp;nbsp;/usr/libexec/valgrind/default.supp &lt;br /&gt;==121593== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-121593-by-test-on-localhost.localdomain &lt;br /&gt;==121593== embedded gdbserver: writing to&amp;nbsp;&amp;nbsp;&amp;nbsp;/tmp/vgdb-pipe-to-vgdb-from-121593-by-test-on-localhost.localdomain &lt;br /&gt;==121593== embedded gdbserver: shared mem&amp;nbsp;&amp;nbsp;&amp;nbsp;/tmp/vgdb-pipe-shared-mem-vgdb-121593-by-test-on-localhost.localdomain &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;TO&amp;nbsp;CONTROL&amp;nbsp;THIS&amp;nbsp;PROCESS&amp;nbsp;USING&amp;nbsp;vgdb&amp;nbsp;(which&amp;nbsp;you&amp;nbsp;probably &lt;br /&gt;==121593==&amp;nbsp;don't&amp;nbsp;want&amp;nbsp;to&amp;nbsp;do,&amp;nbsp;unless&amp;nbsp;you&amp;nbsp;know&amp;nbsp;exactly&amp;nbsp;what&amp;nbsp;you're&amp;nbsp;doing, &lt;br /&gt;==121593==&amp;nbsp;or&amp;nbsp;are&amp;nbsp;doing&amp;nbsp;some&amp;nbsp;strange&amp;nbsp;experiment): &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;/usr/libexec/valgrind/../../bin/vgdb&amp;nbsp;--pid=121593&amp;nbsp;...command... &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;TO&amp;nbsp;DEBUG&amp;nbsp;THIS&amp;nbsp;PROCESS&amp;nbsp;USING&amp;nbsp;GDB:&amp;nbsp;start&amp;nbsp;GDB&amp;nbsp;like&amp;nbsp;this &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;/path/to/gdb&amp;nbsp;./test &lt;br /&gt;==121593==&amp;nbsp;and&amp;nbsp;then&amp;nbsp;give&amp;nbsp;GDB&amp;nbsp;the&amp;nbsp;following&amp;nbsp;command &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;target&amp;nbsp;remote&amp;nbsp;|&amp;nbsp;/usr/libexec/valgrind/../../bin/vgdb&amp;nbsp;--pid=121593 &lt;br /&gt;==121593==&amp;nbsp;--pid&amp;nbsp;is&amp;nbsp;optional&amp;nbsp;if&amp;nbsp;only&amp;nbsp;one&amp;nbsp;valgrind&amp;nbsp;process&amp;nbsp;is&amp;nbsp;running &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4019e40&amp;nbsp;(ld-linux-x86-64.so.2:strlen)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x580c7ed5&amp;nbsp;(???) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4019c10&amp;nbsp;(ld-linux-x86-64.so.2:index)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x580c7eef&amp;nbsp;(???) &lt;br /&gt;--121593--&amp;nbsp;Reading&amp;nbsp;syms&amp;nbsp;from&amp;nbsp;/usr/libexec/valgrind/vgpreload_core-amd64-linux.so &lt;br /&gt;--121593--&amp;nbsp;Reading&amp;nbsp;syms&amp;nbsp;from&amp;nbsp;/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so &lt;br /&gt;==121593==&amp;nbsp;WARNING:&amp;nbsp;new&amp;nbsp;redirection&amp;nbsp;conflicts&amp;nbsp;with&amp;nbsp;existing&amp;nbsp;--&amp;nbsp;ignoring&amp;nbsp;it &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;old:&amp;nbsp;0x04019e40&amp;nbsp;(strlen&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;R-&amp;gt;&amp;nbsp;(0000.0)&amp;nbsp;0x580c7ed5&amp;nbsp;??? &lt;br /&gt;--121593--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new:&amp;nbsp;0x04019e40&amp;nbsp;(strlen&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;R-&amp;gt;&amp;nbsp;(2007.0)&amp;nbsp;0x04c2d1b0&amp;nbsp;strlen &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4019dc0&amp;nbsp;(ld-linux-x86-64.so.2:strcmp)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4c2e300&amp;nbsp;(strcmp) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x401aa80&amp;nbsp;(ld-linux-x86-64.so.2:mempcpy)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4c31f90&amp;nbsp;(mempcpy) &lt;br /&gt;--121593--&amp;nbsp;Reading&amp;nbsp;syms&amp;nbsp;from&amp;nbsp;/usr/lib64/libc-2.17.so &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4ec71d0&amp;nbsp;(libc.so.6:strcasecmp)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4a247a0&amp;nbsp;(_vgnU_ifunc_wrapper) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4ec3f40&amp;nbsp;(libc.so.6:strnlen)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4a247a0&amp;nbsp;(_vgnU_ifunc_wrapper) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4ec94d0&amp;nbsp;(libc.so.6:strncasecmp)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4a247a0&amp;nbsp;(_vgnU_ifunc_wrapper) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4ec69a0&amp;nbsp;(libc.so.6:memset)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4a247a0&amp;nbsp;(_vgnU_ifunc_wrapper) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4ec6950&amp;nbsp;(libc.so.6:memcpy@GLIBC_2.2.5)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4a247a0&amp;nbsp;(_vgnU_ifunc_wrapper) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4ec5930&amp;nbsp;(libc.so.6:__GI_strrchr)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4c2cb70&amp;nbsp;(__GI_strrchr) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4ebc740&amp;nbsp;(libc.so.6:malloc)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4c29eec&amp;nbsp;(malloc) &lt;br /&gt;--121593--&amp;nbsp;REDIR:&amp;nbsp;0x4ebcb60&amp;nbsp;(libc.so.6:free)&amp;nbsp;redirected&amp;nbsp;to&amp;nbsp;0x4c2afe6&amp;nbsp;(free) &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;Process&amp;nbsp;terminating&amp;nbsp;with&amp;nbsp;default&amp;nbsp;action&amp;nbsp;of&amp;nbsp;signal&amp;nbsp;2&amp;nbsp;(SIGINT) &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;at&amp;nbsp;0x4EFC9E0:&amp;nbsp;__nanosleep_nocancel&amp;nbsp;(in&amp;nbsp;/usr/lib64/libc-2.17.so) &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;by&amp;nbsp;0x4EFC893:&amp;nbsp;sleep&amp;nbsp;(in&amp;nbsp;/usr/lib64/libc-2.17.so) &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;by 0x40062F: main (in /home/test/test) &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;HEAP&amp;nbsp;SUMMARY:&lt;/span&gt; &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&amp;nbsp;in&amp;nbsp;use&amp;nbsp;at&amp;nbsp;exit:&amp;nbsp;900,000,000&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;9&amp;nbsp;blocks&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;==121593==&amp;nbsp;&lt;b&gt;&amp;nbsp;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&amp;nbsp;total&amp;nbsp;heap&amp;nbsp;usage:&amp;nbsp;18&amp;nbsp;allocs,&amp;nbsp;9&amp;nbsp;frees,&amp;nbsp;1,800,000,000&amp;nbsp;bytes&amp;nbsp;allocated&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;Searching&amp;nbsp;for&amp;nbsp;pointers&amp;nbsp;to&amp;nbsp;9&amp;nbsp;not-freed&amp;nbsp;blocks&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;==121593==&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&amp;nbsp;Checked&amp;nbsp;70,064&amp;nbsp;bytes&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;400,000,000&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;4&amp;nbsp;blocks&amp;nbsp;are&amp;nbsp;definitely&amp;nbsp;lost&amp;nbsp;in&amp;nbsp;loss&amp;nbsp;record&amp;nbsp;1&amp;nbsp;of&amp;nbsp;2 &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;at&amp;nbsp;0x4C29F73:&amp;nbsp;malloc&amp;nbsp;(vg_replace_malloc.c:309) &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;by 0x400602: malloc_leak (in /home/test/test) &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;by 0x400620: main (in /home/test/test) &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;500,000,000&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;5&amp;nbsp;blocks&amp;nbsp;are&amp;nbsp;possibly&amp;nbsp;lost&amp;nbsp;in&amp;nbsp;loss&amp;nbsp;record&amp;nbsp;2&amp;nbsp;of&amp;nbsp;2 &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;at&amp;nbsp;0x4C29F73:&amp;nbsp;malloc&amp;nbsp;(vg_replace_malloc.c:309) &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;by 0x400602: malloc_leak (in /home/test/test) &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;by 0x400620: main (in /home/test/test) &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;LEAK&amp;nbsp;SUMMARY:&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&amp;nbsp;definitely&amp;nbsp;lost:&amp;nbsp;400,000,000&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;4&amp;nbsp;blocks&lt;/span&gt; &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;indirectly&amp;nbsp;lost:&amp;nbsp;0&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;0&amp;nbsp;blocks &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;possibly&amp;nbsp;lost:&amp;nbsp;500,000,000&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;5&amp;nbsp;blocks&lt;/span&gt; &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;still&amp;nbsp;reachable:&amp;nbsp;0&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;0&amp;nbsp;blocks &lt;br /&gt;==121593==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;suppressed:&amp;nbsp;0&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;0&amp;nbsp;blocks &lt;br /&gt;==121593==&amp;nbsp; &lt;br /&gt;==121593==&amp;nbsp;ERROR&amp;nbsp;SUMMARY:&amp;nbsp;2&amp;nbsp;errors&amp;nbsp;from&amp;nbsp;2&amp;nbsp;contexts&amp;nbsp;(suppressed:&amp;nbsp;0&amp;nbsp;from&amp;nbsp;0)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;valgrind를 통해 작성된 mem.log 내용을 확인하는 중요한 섹션은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;HEAP SUMMARY&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;프로그램 종료 시점에 사용된 메모리와 할당된 메모리의 요약이 제공됨&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 로그를 확인해 보면 HEAP SUMMARY에서 &lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&amp;nbsp;in&amp;nbsp;use&amp;nbsp;at&amp;nbsp;exit:&amp;nbsp;900,000,000&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;9&amp;nbsp;blocks&lt;/span&gt;&lt;/b&gt;라고 출력되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 종료 시점에 할당된 메모리 중 해제되지 않은 메모리를 나타내는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 내가 만든 test 모듈은 인터럽트를 걸어 종료했을 당시 약 900메가가 할당되지 못하고 여전히 사용중이었다는 의미이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt; total heap usage&lt;/span&gt;&amp;nbsp;&lt;/b&gt;를확인해 보면 총 할당 및 해제된 메모리 블록 수와 그 크기를 확인할 수 있는데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 18번의 할당과 9번의 해제가 있었으며, 총 1,800,000,000바이트가 할당됨을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 while문이 18번 도는 동안 2개의 함수를 실행하는데, malloc_free함수에서는 free를 하지만 malloc_leak에서는 free를 하지 않으므로 정확히 절반만 해제되었다는 리포트를 받을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;LEAK SUMMARY&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;프로그램 실행 후 메모리 누수 상태를 요약하여 제공&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;definitely lost&lt;/b&gt;&lt;/span&gt; 는 메모리 누수가 확실한 경우를 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근을 더이상 참조되지 않는 메모리를 나타내는데,&amp;nbsp; 위 로그를 확인해보면 약 400MB가 확실히 누수되고 있음을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt; possibly lost&lt;/b&gt;&lt;/span&gt; 는 메모리 누수 가능성이 있는 경우를 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 블록들은 접근할 수 없는 상태일 가능성이 있으나, 완전히 누수되었다고 확정할 수는 없는 범주를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 로그에서 는 약 500MB가 이 범주에 속한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면, 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;u&gt;손상된 포인터&lt;/u&gt; &lt;br /&gt;: 프로그램 내에서 포인터가 손상되었거나, 잘못된 위치를 가리키고 있는경우&lt;/li&gt;
&lt;li&gt;&lt;u&gt;이중해제 이후의 접근&lt;/u&gt;&lt;br /&gt;: 메모리를 두 번 해제한 후 해당 메모리에 접근하려고 시도하면, 포인터는 더 이상 유효한 메모리를 가리키지는 않지만 여전히 참조하는 것으로 간주될 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;u&gt;오프셋된 포인터&lt;/u&gt;&lt;br /&gt;: 동적 메모리 할당 후, 포인터가 실제 할당된 메모리의 시작 위치에서 오프셋된 위치를 가리키는 경우.&lt;br /&gt;예를 들어 포인터를 이동한 후 해제하지 않고 프로그램을 종료하는 경우(인터럽트의 경우 가능성이 높음)를 말함&lt;/li&gt;
&lt;li&gt;&lt;u&gt;중간에 사라진 참조&lt;/u&gt;&lt;br /&gt;: 프로그램이 동적으로 메모리를 할당한 후, 그 메모리를 가리키는 포인터를 중간에 잃어버린 경우.&lt;br /&gt;예를 들어, 포인터를 잘못된 위치로 설정하거나 포인터를 다른 메모리 주소로 덮어쓰는 경우&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;맞지 않는 메모리 관리&lt;br /&gt;&lt;/u&gt;: 메모리 할당과 해제가 다른 라이브러리나 모듈에서 이루어질 때, 메모리가 제대로 관리되지 않았다고 추정될 수 있음&lt;br /&gt;예를 들어, 커스텀 메모리 관리 함수나 서브 시스템이 있다면 그 내부에서 메모리가 어떻게 관리되고 있는지 valgrind는 명확히 파악할 수 없으므로 누수 여부를 알 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt; &lt;b&gt;indirectly lost &lt;/b&gt;&lt;/span&gt;는 누수된 포인터가 다른 메모리를 가리키고 있던 경우를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 A구조체 안에 B구조체 포인터가 있는데, B를 메모리 할당하고, A를 해제하지 않고 지속적으로 새로 할당 해 누수가 발생되면 B는 이 항목의 누수로 집계된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt; still reachable&lt;/span&gt;&lt;/b&gt; 는 프로그램 종료 시점에 여전히 접근 가능한 ㅔ모리 블록을 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리가 해제되지 않았지만, 프로그램 종료 시점까지 여전히 참조 가능한 상태로 남아있는 메모리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 항목은 의도적으로 사용중인 메모리 일 수 있으므로, 의도한 접근이라면 누수로 판단하지는 않을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt; suppressed &lt;/b&gt;&lt;/span&gt;는 무시된 메모리 누수 오류의 크기와 개수를 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 항목은 개발자가 이전에 무시하도록 설정한 것이며 valgrind는 이를 보고하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 로그를 통해 종합적으로 봤을 때 main에서 호출 된&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;malloc_leak&lt;span&gt; 에서 메모리 누수가 발생하고 있음을 예측할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;그럼 다시 free 주석을 풀어 누수를 막고 다시 확인해보자.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;그리고 이번엔 로그에 담지않고, 바로 콘솔에 출력하도록 해보겠다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1724132964324&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;valgrind --leak-check=summary -v --error-limit=no ./test&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;==8457==&amp;nbsp;Process&amp;nbsp;terminating&amp;nbsp;with&amp;nbsp;default&amp;nbsp;action&amp;nbsp;of&amp;nbsp;signal&amp;nbsp;2&amp;nbsp;(SIGINT) &lt;br /&gt;==8457==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;at&amp;nbsp;0x4EFC9E0:&amp;nbsp;__nanosleep_nocancel&amp;nbsp;(in&amp;nbsp;/usr/lib64/libc-2.17.so) &lt;br /&gt;==8457==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;by&amp;nbsp;0x4EFC893:&amp;nbsp;sleep&amp;nbsp;(in&amp;nbsp;/usr/lib64/libc-2.17.so) &lt;br /&gt;==8457==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;by 0x40063B: main (in /home/test/test) &lt;br /&gt;==8457==&amp;nbsp; &lt;br /&gt;==8457==&amp;nbsp;HEAP&amp;nbsp;SUMMARY: &lt;br /&gt;==8457==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;in&amp;nbsp;use&amp;nbsp;at&amp;nbsp;exit:&amp;nbsp;0&amp;nbsp;bytes&amp;nbsp;in&amp;nbsp;0&amp;nbsp;blocks &lt;br /&gt;==8457==&amp;nbsp;&amp;nbsp;&amp;nbsp;total&amp;nbsp;heap&amp;nbsp;usage:&amp;nbsp;4&amp;nbsp;allocs,&amp;nbsp;4&amp;nbsp;frees,&amp;nbsp;400,000,000&amp;nbsp;bytes&amp;nbsp;allocated &lt;br /&gt;==8457==&amp;nbsp; &lt;br /&gt;==8457==&amp;nbsp;All&amp;nbsp;heap&amp;nbsp;blocks&amp;nbsp;were&amp;nbsp;freed&amp;nbsp;--&amp;nbsp;no&amp;nbsp;leaks&amp;nbsp;are&amp;nbsp;possible &lt;br /&gt;==8457==&amp;nbsp; &lt;br /&gt;==8457==&amp;nbsp;ERROR&amp;nbsp;SUMMARY:&amp;nbsp;0&amp;nbsp;errors&amp;nbsp;from&amp;nbsp;0&amp;nbsp;contexts&amp;nbsp;(suppressed:&amp;nbsp;0&amp;nbsp;from&amp;nbsp;0&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누수가 없어지니 위와 같이 깔끔하게 뜨는 것을 확인할 수 있다.&lt;/p&gt;</description>
      <category>OS/Linux</category>
      <category>memory leak</category>
      <category>valgrind</category>
      <category>누수 위치</category>
      <category>누수 위치 확인</category>
      <category>리눅스 leak</category>
      <category>메모리 leak</category>
      <category>메모리 누수</category>
      <category>메모리 릭</category>
      <category>발그린드</category>
      <category>밸그라인드</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/46</guid>
      <comments>https://elephant-dev.tistory.com/46#entry46comment</comments>
      <pubDate>Tue, 20 Aug 2024 15:19:07 +0900</pubDate>
    </item>
    <item>
      <title>[NCP] 프로젝트에 NCP 활용 후기</title>
      <link>https://elephant-dev.tistory.com/45</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab에서&amp;nbsp; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Green Developers 프로그램을 통해 크레딧을 지원받아 프로젝트에 활용해 보았다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아직 프로젝트 완성은 되지 않았지만 지금까지 사용한 내용을 바탕으로 후기를 작성해보고자 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a6bc00;&quot;&gt;&lt;b&gt;Q. 프로젝트를 소개해 주세요.&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현하고자 하는 프로젝트 주제는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Melon Market과 같이 공연을 예매하는 서비스를 구현하고, 추가적으로 내 업무 경력을 살려 서버를 모니터링 할 수 있을 것&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존 개발 환경에서는 대용량 데이터를 어떻게 처리하는지, 다뤄볼 기회가 없어 매우 궁금했었고 내가 좋아하는 것에 대한 서비스를 생각했을 때 대용량 데이터를 처리하고 있는 서비스가 뭐였는지 생각해 보니..!&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최근에 멤피스 뮤지컬과 최유리 콘서트를 예매하기 위해 애썼던 기억이 떠올랐다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러고 보니 특정 기간 특정 시간에 이렇게 많은 사람들이 몰리는 이 서버를 어떻게 처리하고 있는 걸까?라고 궁금했었고,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;'대용량 데이터 처리'에 중점을 두고 어떻게 구현하면 좋고 기술은 어떤 것들을 선택해야 좋은지에 대해 공부도 하고 직접 대용량 데이터 처리에서 어떤 문제점을 마주칠 수 있고, 그 문제를 해결하기 위한 고민을 하고 잘 해결해 내는 경험을 하고자 해당 주제를 선택하게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물론! 대용량 데이터를 직접 다뤄볼 순 없겠지만, 부하 테스트를 통해 할 수 있는 한.. 내가 낼 수 있는 최대 성능을 끌어올려 효율적으로 문제를 해결해 나가 보는 것으로 대용량 데이터 처리에 대해 조금은 학습할 수 있을 것이라 생각했다!&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712119873835&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - f-lab-edu/melody-market: 멜론티켓 서비스를 예시로한, 음악과 관련된 공연 티켓팅 서비스입니&quot; data-og-description=&quot;멜론티켓 서비스를 예시로한, 음악과 관련된 공연 티켓팅 서비스입니다. Contribute to f-lab-edu/melody-market development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/f-lab-edu/melody-market&quot; data-og-url=&quot;https://github.com/f-lab-edu/melody-market&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/L2NuO/hyVGDvlPiM/gmraCLwcmIYZH8mnIQmL50/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/f-lab-edu/melody-market&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/f-lab-edu/melody-market&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/L2NuO/hyVGDvlPiM/gmraCLwcmIYZH8mnIQmL50/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - f-lab-edu/melody-market: 멜론티켓 서비스를 예시로한, 음악과 관련된 공연 티켓팅 서비스입니&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;멜론티켓 서비스를 예시로한, 음악과 관련된 공연 티켓팅 서비스입니다. Contribute to f-lab-edu/melody-market development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a6bc00;&quot;&gt;&lt;b&gt;Q. Ncloud에서 어떤 서비스를 활용하셨나요?&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대용량 데이터 처리에 중심은 분산 시스템이라고 생각했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특정 시간에 혹은 특정 날짜에 사용자가 몰릴 것을 대비하여 그 많은 트래픽을 어떻게 처리할 수 있을까?! 고민하고,&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관련 내용을 학습하던 중 '수평적 확장'을 통해 트래픽을 분산하는 것에 대해 알게 되었고,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;수평적 확장을 위해서는 웹 서버로 들어오는 트래픽을 여러 서버에 올바르게 분산시켜 한 곳에 트래픽이 몰리지 않는 것이 중요하다는 것을 알게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 NCP에&amp;nbsp; Ncloud&amp;nbsp; kubernetes service를 이용해 CI/CD부터 로드밸런스를 활용한 부하 분산 및 수평적 확장이 가능하도록 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;서버를 구성하고,&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;또 빌드한 이미지는 NCP의 Container Registry에 올려 관리할 수 있게 하였다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1712120204917&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편&quot; data-og-description=&quot;프로젝트를 진행하면서, 롤링 업데이트 배포 전략을 사용하기 위해 F-Lab을 통해 네이버 클라우드 플랫폼 에서 사용할 수 있는 크레딧을 제공 받아NCP에서 제공해주는 쿠버네티스를 이용해 보았&quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/41&quot; data-og-url=&quot;https://elephant-dev.tistory.com/41&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eJQBY/hyVGKHYaPO/gzP2LmPx4E4vyzVWHhmDR1/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/BIx7n/hyVGFzUapx/CZt2adeFvsn6LgTwce2Ns0/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/dFjhg2/hyVGEHOeKW/rbF1fTcMuURWdO59w66S01/img.png?width=669&amp;amp;height=690&amp;amp;face=0_0_669_690&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/41&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/41&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eJQBY/hyVGKHYaPO/gzP2LmPx4E4vyzVWHhmDR1/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/BIx7n/hyVGFzUapx/CZt2adeFvsn6LgTwce2Ns0/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/dFjhg2/hyVGEHOeKW/rbF1fTcMuURWdO59w66S01/img.png?width=669&amp;amp;height=690&amp;amp;face=0_0_669_690');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트를 진행하면서, 롤링 업데이트 배포 전략을 사용하기 위해 F-Lab을 통해 네이버 클라우드 플랫폼 에서 사용할 수 있는 크레딧을 제공 받아NCP에서 제공해주는 쿠버네티스를 이용해 보았&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1712120241695&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편&quot; data-og-description=&quot;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는 &quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/42&quot; data-og-url=&quot;https://elephant-dev.tistory.com/42&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bA0wUw/hyVJZXMNdy/F7ZGK9bvLyjNOXjAy82b7K/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/bdkTWh/hyVGEA1GXz/Wy9GKAzXgk6XqUatWzSQG1/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/gR9B3/hyVJRMeVrT/5WWq63CiBJqpWlZdHkflWK/img.png?width=1620&amp;amp;height=682&amp;amp;face=0_0_1620_682&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/42&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/42&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bA0wUw/hyVJZXMNdy/F7ZGK9bvLyjNOXjAy82b7K/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/bdkTWh/hyVGEA1GXz/Wy9GKAzXgk6XqUatWzSQG1/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/gR9B3/hyVJRMeVrT/5WWq63CiBJqpWlZdHkflWK/img.png?width=1620&amp;amp;height=682&amp;amp;face=0_0_1620_682');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a6bc00;&quot;&gt; &lt;b&gt;Q. Ncloud 서비스를 어떻게 적용하였나요?&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;443&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2bk74/btsGj48LRa2/h4skbLxEd8qiKuzXTjNcK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2bk74/btsGj48LRa2/h4skbLxEd8qiKuzXTjNcK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2bk74/btsGj48LRa2/h4skbLxEd8qiKuzXTjNcK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2bk74%2FbtsGj48LRa2%2Fh4skbLxEd8qiKuzXTjNcK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;812&quot; height=&quot;443&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;443&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ncloud를 운영 서버로 활용하기 위해 소스코드 커밋 시 github-action을 통해 빌드를 진행하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Container Registry에 이미지를 업로드하고, kubernetes 접속 서버 전용으로 만든 서버에 ssh로 접속하여 Rolling Update 방식으로 Kubernetes pod들을 새롭게 배포하도록 하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세한 내용은 포스팅으로 작성해 두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1712120492282&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[GIT] github-action으로 빌드, 쿠버네티스 클러스터에 배포하기 (with Naver Cloud Platform)&quot; data-og-description=&quot;github action을 통해 소스코드 커밋 혹은 머지 시 빌드와 테스트 하고, NCP Container Registry로 이미지 push 후 다시 pull 받아 쿠버네티스 클러스터에 Rolling Update 배포 전략을 사용하여 배포하는 방법에 &quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/43&quot; data-og-url=&quot;https://elephant-dev.tistory.com/43&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bhdHOh/hyVJYxOb9D/pNRKWruHmiwTFy0KqASdeK/img.png?width=800&amp;amp;height=441&amp;amp;face=698_0_748_55,https://scrap.kakaocdn.net/dn/mtMH1/hyVJSRUcMH/zIrkfyLns25TzefR5V4BKk/img.png?width=800&amp;amp;height=441&amp;amp;face=698_0_748_55,https://scrap.kakaocdn.net/dn/bGRccw/hyVJS5qHIa/xLVXGifFmkYqTvU94u8uEK/img.png?width=1725&amp;amp;height=1130&amp;amp;face=0_0_1725_1130&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/43&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/43&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bhdHOh/hyVJYxOb9D/pNRKWruHmiwTFy0KqASdeK/img.png?width=800&amp;amp;height=441&amp;amp;face=698_0_748_55,https://scrap.kakaocdn.net/dn/mtMH1/hyVJSRUcMH/zIrkfyLns25TzefR5V4BKk/img.png?width=800&amp;amp;height=441&amp;amp;face=698_0_748_55,https://scrap.kakaocdn.net/dn/bGRccw/hyVJS5qHIa/xLVXGifFmkYqTvU94u8uEK/img.png?width=1725&amp;amp;height=1130&amp;amp;face=0_0_1725_1130');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[GIT] github-action으로 빌드, 쿠버네티스 클러스터에 배포하기 (with Naver Cloud Platform)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;github action을 통해 소스코드 커밋 혹은 머지 시 빌드와 테스트 하고, NCP Container Registry로 이미지 push 후 다시 pull 받아 쿠버네티스 클러스터에 Rolling Update 배포 전략을 사용하여 배포하는 방법에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a6bc00;&quot;&gt; &lt;b&gt;Q. Ncloud 사용 중 특히 만족했던 점과, 아쉬웠던 점은 무엇인가요?&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Ncloud를 사용 중 만족했던 점은 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 처음 콘솔에 들어갔을 때 한국어로 되어있는 점이 좋았다..!&lt;br /&gt;이전에 Oracle Cloud를 이용해 개발했던 경험이 있어서 한글이 잘 쓰여있는 것만으로도 얼마나 감격스러운 일인지 모른다ㅜ_ㅜ&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. UI 디자인이 엄청 깔끔하다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;네이버의 디자인은 항상 깔끔하게 잘 만드는 것 같다. 그래서 어떤 기능들이 있는지 분류가 잘 되어있고 깔끔한 디자인 덕에 필요한 기능을 손쉽게 찾을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 고객 문의 대응이 빠르다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 짧은 과정을 하면서도 엄청 모르는 것들이 많아서 시간이 많이 소요되곤 했었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 문의하기 기능을 통해 문의를 하면 정말 빠른 시간 안에 답변을 주신다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;길면 하루? 정도 안에 답변을 해주시는 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러나 아쉬운 점도 역시 존재했다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;다른 플랫폼과 같이 교육 패키지가 있으면 좋았을 것 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 작은 규모의 프로젝트를 실행하기에 적절한 비용의 서버를 추천해 준다던지 기능을 사용하지 않는데 계속 살려두어 비용이 부과되고 있다면 아무런 기능을 하지 않고 있다던지.. 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Ncloud&amp;nbsp; kubernetes service를 이용하기 위해 필요한 것들을 다 생성하고 나니 서버는 끄고 있는데 비용이 내 기준&amp;nbsp;너무 많이 소요되고 있는 것 같다 그래서 나한텐 적어도 그런 기능이 있었다면 공부를 위한 크레딧을 헛으로 날리는 일은 없지 않았을까 싶다ㅠㅠ너무 아깝다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a6bc00;&quot;&gt; &lt;b&gt;Q. Green Developers 프로그램 참여 소감 말씀 부탁 드립니다.&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Green Developers 프로그램에 참여한 덕분에 많은 부분에 학습할 기회가 충분히 생겼던 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부하는 입장에서는 서버를 많이 만들어보고 실패도 해보고 여러 가지 경험들이 꽤 필요한데 Green Developers 프로그램이 없었더라면 공부를 하는데에 제한되는 환경이 정말 많았을 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 Green Developers 프로그램을 통해 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;kubernetes에 대해 공부해 볼 수 있는 기회가 생겨 너무 값진 경험이을 할 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a6bc00;&quot;&gt; &lt;b&gt;Q. 마지막 한 말씀 부탁 드립니다.&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;CI/CD를 진행할 때 이미 가지고 있는 이미지가 있어서 해당 이미지를 Container Registry 태그가 변경되면(최신 이미지가 올라오면) 자동으로 배포되게 연동하고 싶었으나.. 문의를 해보았을 땐 Source Build기능을 사용하면 된다고 했다..!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Source Deploy로 충분히 가능한 일인 줄 알았는데.. 해당 기능은 Zip 파일만 배포 가능하다고 하여 속상했다..&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;추가로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Source Build기능은 현재 내가 설정한 내용으로도 비용이 만만치 않게 소모되고 있고 이미 구현해 놓은 빌드 기능이 있어 진행하지는 않았던 경험이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 아쉬운 점은 내가 알고 있는 지식이 많지 않아 생겼던 지식인 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아마 더 자세히 알고 있는 사람들은 더 효율적이게 사용할 수 있지 않을까 싶다..!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 추후엔&amp;nbsp;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;Source Build기능을 이용해서 좀 더 완벽히 기능을 사용해내보고 싶다!!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;또한 네이버 클라우드 플랫폼 유저 커뮤니티 카톡방을 통해서 다양한 지식을 얻을 수 있어서 좋았다..! &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;처&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;음엔 궁금한 거 질문하러 들어갔다가 유용한 내용이 많아 나가지 않고 계속 보면서 지식을 얻고 있다ㅎㅎ 이런 부분들에서 많은 고민을 하고 프로그램들을 구축해 나가고 있는 것 같아서 좋았다!&lt;/span&gt;&lt;/p&gt;</description>
      <category>회고</category>
      <category>Green Developers</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/45</guid>
      <comments>https://elephant-dev.tistory.com/45#entry45comment</comments>
      <pubDate>Wed, 3 Apr 2024 14:25:46 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 좌석 개수를 구하기 위한 @Formula 사용기 (Feat. @DataJpaTest @Formula 데이터 검증 테스트 실패 분석)</title>
      <link>https://elephant-dev.tistory.com/44</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인 프로젝트 진행 중 공연장에 등록된 hall을 리스트로 조회하는 API를 구현하면서 각 hall에 설정된 좌석수를 간단히 보여주고 싶었다.&lt;br /&gt;이 때 모든 hall 리스트가 보여지더라도, 모든 hall에 대한 좌석 세부 정보를 확인하지 않을 거라 생각하기 때문에 &lt;br /&gt;좌석 정보를 조회하는 부분과 hall을 조회하는 부분을 나누어 필요하지 않은 데이터까지 로딩하지 않는 목표를 세웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공연장과 공연장에 존재하는 홀, 홀에 존재하는 좌석 이렇게 세개의 테이블은 서로 연관관계를 가지는 테이블로 구성되어있고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홀에 존재하는 좌석 수를 구하는 방법 중 4가지 방법을 고안하고 고민했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;고민했던 4가지 방안&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 공연홀을 조회하고, 각 좌석의 리스트 개수를 조회하기&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 공연홀을 조회한 후 각 공연 홀에 대한 좌석 수 카운팅 하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. @Formula를 사용하여 공연홀 조회와 동시에 좌석 수 카운팅 하기&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. JPQL 사용해서 좌석 수 조회 하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 공연홀을 조회하고, 각 좌석의 리스트 개수를 조회하기&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711801155877&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*  공연 홀 엔티티 내부에 선언되어있는 좌석 엔티티
	@OneToMany(mappedBy = &quot;theaterRoom&quot;, cascade = CascadeType.ALL)
    private List&amp;lt;TheaterSeat&amp;gt; seats;
*/

public List&amp;lt;TheaterRoomResponseDto&amp;gt; getTheaterRoomList(Long userId, Long theaterId, int pageNo, String criteria) {
    Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE, Sort.by(Sort.Direction.DESC, criteria));
    Page&amp;lt;TheaterRoom&amp;gt; theaterRoomsPage = theaterRoomRepository.findTheaterRoomsByTheaterId(theaterId, pageable);
    if (theaterRoomsPage.isEmpty()) {
        throw new DataNotFoundException(&quot;공연에 등록된 Hall이 없습니다.&quot;);
    }

    theaterRoomsPage.getContent().forEach(room -&amp;gt; room.setSeatCount(room.seats.size()));

    return responseMapper.toTheaterRoomResponseDto(theaterRoomsPage);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법은 고안한 방법 중 성능측면에서 가장 비효율적인 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@OneToMany의 경우 따로 fetch type을 지정해주지 않는다면 LAZY 이며 LAZY 인 경우, 호출되는 순간 데이터가 로드되는 지연 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 목표한 바는 필요없는 정보 즉, 아직 정보 조회를 요청하지 않는 정보까지 로드하지 말자는 것이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 seats 리스트의 사이즈를 얻는 순간 seats의 데이터가 리스트에 채워지게 되므로 결국 모든 영속되어있는 데이터를 다 조회하는 꼴이 되어버려 성능 비효율이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뿐만 아니라 모든 공연 홀 리스트를 순회하면서 좌석의 수를 세팅해주어야 하기 때문에 이 또한 hall이 많아질수록 비효율이 발생할 것이라 판단했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이 방법은 탈락이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 공연홀을 조회한 후 각 공연 홀에 대한 좌석을 조회하기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711799722650&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public List&amp;lt;TheaterRoomResponseDto&amp;gt; getTheaterRoomList(Long userId, Long theaterId, int pageNo, String criteria) {
        Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE, Sort.by(Sort.Direction.DESC, criteria));
        Page&amp;lt;TheaterRoom&amp;gt; theaterRoomsPage = theaterRoomRepository.findTheaterRoomsByTheaterId(theaterId, pageable);
        if (theaterRoomsPage.isEmpty()) {
            throw new DataNotFoundException(&quot;공연에 등록된 Hall이 없습니다.&quot;);
        }
	
        theaterRoomsPage.getContent().forEach(room -&amp;gt; room.setSeatCount(theaterSeatRepository.findSeatCountByTheaterRoomId(room.getId())));

        return responseMapper.toTheaterRoomResponseDto(theaterRoomsPage);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법은 TheaterRoomList 조회에 theaterRoomRepository만 관여하게 하고싶은데 theaterSeatRepository가 관여되는 것이 통일성 측면에서 깨진다고 생각했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 1번의 방법과 동일하게 모든 공연 홀 리스트를 순회하면서 좌석의 수를 세팅해주어야 하기 때문에 이 또한 hall이 많아질수록 비효율이 발생할 것이라 판단했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. @Formula를 사용하여 공연홀 조회와 동시에 좌석 수 카운팅 하기&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711802218235&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class TheaterRoom {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = &quot;theater_id&quot;)
    private Theater theater;
    @Column
    private String name;

    @OneToMany(mappedBy = &quot;theaterRoom&quot;, cascade = CascadeType.ALL)
    private List&amp;lt;TheaterSeat&amp;gt; seats;
    @Formula(&quot;(SELECT COUNT(s.id) FROM seat s WHERE s.theater_room_id = id)&quot;)
    private int seatCount;
    // 하단 생략&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Formula를 사용해서 공연 홀을 조회할 때 seatCount까지 조회 하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법은 실제 실행해보면 조회 쿼리에 서브쿼리로 들어가게 되는 방식이다. 실제로 수행되는 sql을 출력해 보면 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1711802502067&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;org.hibernate.SQL: select tr1_0.id,tr1_0.name,(SELECT COUNT(s.id) FROM seat s WHERE s.theater_room_id = tr1_0.id),tr1_0.theater_id from theater_room tr1_0 left join theater t1_0 on t1_0.id=tr1_0.theater_id where t1_0.id=?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공연홀을 조회하면서 좌석 개수를 한꺼번에 구할 수 있고, 불필요한 데이터를 로드하지 않아 목표에 부합하여 이 방식을 채택하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Formula 사용시 쿼리가 서브쿼리로 수행되기 때문에 &quot;(쿼리)&quot; 형태로 작성해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. JPQL 사용해서 좌석 수 조회 쿼리 만들기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711803049044&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Repository
public interface TheaterRoomRepository extends JpaRepository&amp;lt;TheaterRoom, Long&amp;gt; {

    @Query(&quot;SELECT COUNT(seat) FROM TheaterSeat seat WHERE seat.theaterRoom.id = :roomId&quot;)
    Long countSeatsByTheaterRoomId(Long roomId);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 2번과 다르게 내가 통일하고 싶던 구조를 해치지 않으면서 수행할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 여전히 list를 모두 돌면서 좌석 수 값을 세팅해주어야 한다는 문제는 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 2번과 동일한 이유로 보류하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 나는 최종적으로 3번 방식을 통해 좌석 수를 구하는 방식을 채택하여 테스트를 진행하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 테스트를 하면서 큰 문제가 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 @Formula를 통해 구한 좌석 수 값을 검증하기 위해 작성한 테스트 코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1711803340265&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@DataJpaTest
@Import({ManageTheaterServiceImpl.class, ResponseMapperImpl.class})
@DisplayName(&quot;공연장 관리 서비스 테스트&quot;)
class TheaterManageServiceImplTest {
    @Autowired
    ManageTheaterService manageTheaterService;
    @Autowired
    TheaterRepository theaterRepository;
    TheaterDto theaterDto;
    final int insertTheaterRoom = 3;
    final int insertSeat = 5;
    final Long userId = 1L;

    @BeforeEach
    void insert() {
        this.theaterDto = createTestTheater(&quot;테스트 공연장&quot;);
        Long userId = 1L;
        manageTheaterService.saveTheater(theaterDto, userId);
    }


    @Test
    @DisplayName(&quot;홀이 등록되어 있는 공연장 홀 리스트 조회 시 성공&quot;)
    void givenRegisterTheaterRoomByTheaterId_whenGetTheaterRoomList_thenGetTheaterRoomListSuccessfully() {
        //given
        Long userId = this.userId;
        List&amp;lt;TheaterResponseDto&amp;gt; theaterResponseDtoList = manageTheaterService.getTheaterList(userId, 0, &quot;name&quot;);
        Long theaterId = theaterResponseDtoList.get(0).getId();
        System.out.println(theaterId);

        //when
        List&amp;lt;TheaterRoomResponseDto&amp;gt; theaterRoomList = manageTheaterService.getTheaterRoomList(userId, theaterId, 0, &quot;name&quot;);

        //then
        Assertions.assertThat(theaterRoomList).hasSize(insertTheaterRoom);
        Assertions.assertThat(theaterRoomList.get(0).getName()).isEqualTo(&quot;test hall2&quot;); // name으로 페이지네이션 했으므로 가장먼저 높은 숫자 출력
        Assertions.assertThat(theaterRoomList.get(0).getSeatCount()).isEqualTo(insertSeat);
    }
  
    private List&amp;lt;TheaterRoomDto&amp;gt; createTestTheaterRooms() {
        List&amp;lt;TheaterRoomDto&amp;gt; roomDtoList = new ArrayList&amp;lt;&amp;gt;();
        for (int i = 0; i &amp;lt; 3; i++) {
            roomDtoList.add(TheaterRoomDto.builder().roomName(&quot;test hall&quot; + i).seatData(createTestTheaterSeats()).build());
        }

        return roomDtoList;
    }

    private List&amp;lt;TheaterSeatDto&amp;gt; createTestTheaterSeats() {
        List&amp;lt;TheaterSeatDto&amp;gt; seatDtoList = new ArrayList&amp;lt;&amp;gt;();
        for (int i = 0; i &amp;lt; 5; i++) {
            seatDtoList.add(TheaterSeatDto.builder().seatFloor(i).seatRow(5).seatNumber(1).build());
        }

        return seatDtoList;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 테스트 코드에서 theaterRoom 데이터는 잘 출력되나, seatCount 가 계속 0으로 나오는 문제가 발생했다.다.Assertions.assertThat(theaterRoomList.get(0).getSeatCount()).isEqualTo(insertSeat);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도대체 뭐가 문제인가..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그 레벨을 낮춰 sql 수행 쿼리를 모두 찍어봐도 다음과 같이 쿼리가 잘 들어가있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-30 오후 10.02.46.png&quot; data-origin-width=&quot;3946&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QegBA/btsGePi5xhE/UwbRMdiKoUpB0ol0eldl4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QegBA/btsGePi5xhE/UwbRMdiKoUpB0ol0eldl4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QegBA/btsGePi5xhE/UwbRMdiKoUpB0ol0eldl4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQegBA%2FbtsGePi5xhE%2FUwbRMdiKoUpB0ol0eldl4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3946&quot; height=&quot;78&quot; data-filename=&quot;스크린샷 2024-03-30 오후 10.02.46.png&quot; data-origin-width=&quot;3946&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-30 오후 10.02.53.png&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;92&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YjQ4N/btsGfLgaW3t/nVDBErRKph37OvBwtoIEa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YjQ4N/btsGfLgaW3t/nVDBErRKph37OvBwtoIEa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YjQ4N/btsGfLgaW3t/nVDBErRKph37OvBwtoIEa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYjQ4N%2FbtsGfLgaW3t%2FnVDBErRKph37OvBwtoIEa1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;196&quot; height=&quot;64&quot; data-filename=&quot;스크린샷 2024-03-30 오후 10.02.53.png&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;92&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어는 브레이크 포인트 잡아서 디버깅도 해 보고 로그도 직접 찍어서 확인해보아도 쿼리는 수행되는데 0으로 찍히는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 h2 데이터베이스를 사용하지 않고 실제 데이터베이스에 데이터를 저장하고 해당 쿼리를 직접 실행해보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-30 오전 12.41.43.png&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHpn4L/btsGdS8VU3C/BMWAx1RD1YbCscwOGQRgBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHpn4L/btsGdS8VU3C/BMWAx1RD1YbCscwOGQRgBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHpn4L/btsGdS8VU3C/BMWAx1RD1YbCscwOGQRgBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHpn4L%2FbtsGdS8VU3C%2FBMWAx1RD1YbCscwOGQRgBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1662&quot; height=&quot;622&quot; data-filename=&quot;스크린샷 2024-03-30 오전 12.41.43.png&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;insert한 데이터도 잘 들어가있고, 쿼리 수행 시에도 서브쿼리에 해당되는 내 @Formula 데이터도 너무나 잘 조회된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 문제의 원인은 @DataJpaTest에 숨어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;@DataJpaTest는 @Transactional이 포함되어있다.&lt;/span&gt; &lt;/b&gt;그리고 내 테스트 코드에는 @BeforeEach를 통해 데이터를 직접 insert하고, insert된 데이터를 통해 검증을 시도한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;JPA의 @Transactional은 insert, update와 같은 dml 쿼리는 성능을 위해 commit이 되기 전까지 영속성 컨텍스트내에만 존재하며 실제 데이터베이스에 작업을 하지 않는다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이것이 왜 문제가 되는가??&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 조회시에는 영속성 컨텍스트에 저장된 데이터를 통해 조회를 잘 해오지만, @Formula 데이터는 insert할 때 필요한 데이터가 아니기 때문에 insert할 때 데이터로 넣어준 적이 없으며 따라서 값을 얻기 위해&amp;nbsp; 데이터베이스에 직접 접근해서 쿼리를 수행하기 때문에 값이 없는것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 JPA @Transactional에 의해 실제 데이터베이스에는 값이 저장되지 않았는데 seatCount값은 필요로 하기 때문에 조회를 데이터베이스에 하려고 하니 값이 0으로 조회되는 것이다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Formula는 자료도 많이 없고 chatgpt도 왜 안되는지 답을 알려주지 않아서 원인 파악에 꽤나 많은 시간을 소요했다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 테스트에서 문제를 해결하려면 @DataJpaTest를 사용하지 않고, @Transactional를 사용하지 않고 @SpringBootTest를 사용하면 성공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 나는 이 테스트 안에서 값이 잘 들어가는지에 대한 테스트도 수행해야 하기 때문에 @Transactional을 사용해야만 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 또 다른 방법은 @BeforeEach로 수행하는것이 아닌 데이터 insert 작업이 필요한 곳에 메서드를 추가해서 작업을 하고 필요한 테스트에만 @Transactional을 수행하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 결론적으로는!&lt;br /&gt;내가 조회하려는 좌석 수는 변동이 잦지 않은 데이터이기 때문에 항상 count를 조회하는 쿼리를 통해 조회하기 된다면 데이터의 성격에 따라 count() 쿼리 자체가 성능적으로 부하가 많을 수 있어 차라리 컬럼으로 넣어 같이 관리하기로 했다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@Formula사용 시 아래와 같은 사항을 잘 고려해서 사용해야한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 성능 문제&lt;br /&gt;@Formula 어노테이션으로 지정된 필드는 해당 엔티티가 로드될 때마다 SQL 표현식이 실행되므로 추가적인 데이터베이스 쿼리를 발생시킬 수 있으며, 복잡한 SQL 표현식이나 대량의 데이터를 처리할 경우 성능 저하를 일으킬 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 휴대성 문제&lt;br /&gt;@Formula에 사용되는 SQL 표현식은  데이터베이스 종류에 종속적일 수 있어 데이터베이스로 전환할 때 SQL 표현식이 호환되지 않을 수 있기 때문에, 데이터베이스 휴대성을 저하시킬 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.&amp;nbsp;유지보수성&lt;br /&gt;@Formula를 사용하는 SQL 표현식은 자바 코드 내에 문자열로 포함되어 있어, IDE의 도움을 받지 못하고, SQL 쿼리의 오류를 컴파일 타임에 발견하기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.&amp;nbsp;보안&amp;nbsp;고려사항&lt;br /&gt;SQL&amp;nbsp;인젝션&amp;nbsp;공격과&amp;nbsp;같은&amp;nbsp;보안&amp;nbsp;취약점에&amp;nbsp;노출될&amp;nbsp;위험이&amp;nbsp;있으므로,&amp;nbsp;@Formula&amp;nbsp;내에&amp;nbsp;사용자&amp;nbsp;입력&amp;nbsp;값을&amp;nbsp;직접&amp;nbsp;포함시키는 것은 피해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5.&amp;nbsp;트랜잭션&amp;nbsp;및&amp;nbsp;데이터&amp;nbsp;일관성&lt;br /&gt;@Formula로 계산된 필드는 읽기 전용이라 이 필드를 통해 계산된 값을 데이터베이스에 저장하거나 업데이트할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특수한 상황에서는 아주 유용하게도 사용될 수 있는 기능인 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 사용하지 않기로 했으나 자료가 없어서 직접 여러가지 찾으면서 분석할 수 있는 기회가 되어 좋은 공부가 되었다!&lt;/p&gt;</description>
      <category>Programming/Spring</category>
      <category>@Formula</category>
      <category>@formula jpa</category>
      <category>FORMULA</category>
      <category>formula jpa</category>
      <category>JPA @Formula</category>
      <category>jpa formula</category>
      <category>엔티티 서브쿼리</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/44</guid>
      <comments>https://elephant-dev.tistory.com/44#entry44comment</comments>
      <pubDate>Sat, 30 Mar 2024 22:25:16 +0900</pubDate>
    </item>
    <item>
      <title>[GIT] github-action으로 빌드, 쿠버네티스 클러스터에 배포하기 (with Naver Cloud Platform)</title>
      <link>https://elephant-dev.tistory.com/43</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github action을 통해 소스코드 커밋 혹은 머지 시 빌드와 테스트 하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NCP Container Registry로 이미지 push 후 다시 pull 받아 쿠버네티스 클러스터에 Rolling Update 배포 전략을 사용하여 배포하는 방법에 대해 정리해보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NCP kubernetes 환경 구축 방법은 아래 포스팅을 참고하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- [NCP]&amp;nbsp;Ncloud&amp;nbsp;Kubernetes&amp;nbsp;Service&amp;nbsp;사용하기(+&amp;nbsp;Container&amp;nbsp;Registry&amp;nbsp;사용&amp;nbsp;까지)&amp;nbsp;-&amp;nbsp;1편&lt;/p&gt;
&lt;figure id=&quot;og_1711071888564&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편&quot; data-og-description=&quot;프로젝트를 진행하면서, 롤링 업데이트 배포 전략을 사용하기 위해 F-Lab을 통해 네이버 클라우드 플랫폼 에서 사용할 수 있는 크레딧을 제공 받아NCP에서 제공해주는 쿠버네티스를 이용해 보았&quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/41&quot; data-og-url=&quot;https://elephant-dev.tistory.com/41&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eNXqR/hyVAHLkLBx/cyp8P6KKiOsUrts27uf3qk/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/jN5Fx/hyVAHq4Z0U/jOxJYPhH9xY58m1pTGkwcK/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/bgOlQD/hyVDxtynIF/zW4CFRcqOXTFADfvy9lwik/img.png?width=1298&amp;amp;height=391&amp;amp;face=0_0_1298_391&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/41&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/41&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eNXqR/hyVAHLkLBx/cyp8P6KKiOsUrts27uf3qk/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/jN5Fx/hyVAHq4Z0U/jOxJYPhH9xY58m1pTGkwcK/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/bgOlQD/hyVDxtynIF/zW4CFRcqOXTFADfvy9lwik/img.png?width=1298&amp;amp;height=391&amp;amp;face=0_0_1298_391');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트를 진행하면서, 롤링 업데이트 배포 전략을 사용하기 위해 F-Lab을 통해 네이버 클라우드 플랫폼 에서 사용할 수 있는 크레딧을 제공 받아NCP에서 제공해주는 쿠버네티스를 이용해 보았&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- [NCP]&amp;nbsp;Ncloud&amp;nbsp;Kubernetes&amp;nbsp;Service&amp;nbsp;사용하기(kubectl&amp;nbsp;사용하여&amp;nbsp;pod&amp;nbsp;생성하기)&amp;nbsp;-&amp;nbsp;2편&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1711071868903&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편&quot; data-og-description=&quot;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는 &quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/42&quot; data-og-url=&quot;https://elephant-dev.tistory.com/42&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Sylof/hyVAAS167q/EuaiimVlMHBF3kEm1x62JK/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/fNHWi/hyVDIPokCw/JQJv0nVB4yPjsMUaFXHt41/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/bMi99M/hyVAzmiI7x/HOzanMSil1weYvCydagUSk/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/42&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/42&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Sylof/hyVAAS167q/EuaiimVlMHBF3kEm1x62JK/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/fNHWi/hyVDIPokCw/JQJv0nVB4yPjsMUaFXHt41/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/bMi99M/hyVAzmiI7x/HOzanMSil1weYvCydagUSk/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;927&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rJJH4/btsFX0meY22/GTuapAGDI6r8QSpXcJ1Kkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rJJH4/btsFX0meY22/GTuapAGDI6r8QSpXcJ1Kkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rJJH4/btsFX0meY22/GTuapAGDI6r8QSpXcJ1Kkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrJJH4%2FbtsFX0meY22%2FGTuapAGDI6r8QSpXcJ1Kkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1680&quot; height=&quot;927&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;927&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;github-action을 통해 내가 얻고 싶은 결과물은 위의 그림과 같다&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 개발자가 소스코드를 GitHub에 커밋 시 (main으로)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 소스코드 빌드 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 단위 테스트 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Docker Image 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Image를 NCP Container Registry에 업로드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. NCP Container Registry에서 이미지를 pull받아 쿠버네티스 클러스터에 롤링업데이트 배포&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 실패 시 롤백&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 처음부터 차근차근 gihub action 사용을 위한 방법을 알아가보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. github-action workflow 생성&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;64&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GGofc/btsF0kKcqpm/5xnWT6Fen4Wt5Ug1j5RovK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GGofc/btsF0kKcqpm/5xnWT6Fen4Wt5Ug1j5RovK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GGofc/btsF0kKcqpm/5xnWT6Fen4Wt5Ug1j5RovK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGGofc%2FbtsF0kKcqpm%2F5xnWT6Fen4Wt5Ug1j5RovK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1153&quot; height=&quot;64&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;64&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github에서 github-action을 만들고 싶은 프로젝트에 들어가 상단 카테고리 중 Actions를 클릭한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 아래와 같이 여러 종류의 템플릿이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자신의 프로젝트에 맞게 선택해주면 되는데, 나의 경우 java with gradle을 선택했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;930&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuJyvM/btsFXIzjAhI/ZZcCpwFdzFl7MJ8LJN92y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuJyvM/btsFXIzjAhI/ZZcCpwFdzFl7MJ8LJN92y0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuJyvM/btsFXIzjAhI/ZZcCpwFdzFl7MJ8LJN92y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuJyvM%2FbtsFXIzjAhI%2FZZcCpwFdzFl7MJ8LJN92y0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1640&quot; height=&quot;930&quot; data-origin-width=&quot;1640&quot; data-origin-height=&quot;930&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A0WMe/btsF0bmiati/kmn6J84cvZ2qEIWfsKgiqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A0WMe/btsF0bmiati/kmn6J84cvZ2qEIWfsKgiqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A0WMe/btsF0bmiati/kmn6J84cvZ2qEIWfsKgiqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA0WMe%2FbtsF0bmiati%2Fkmn6J84cvZ2qEIWfsKgiqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1164&quot; height=&quot;640&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Configure 버튼을 누르면 다음과 같이 내 프로젝트에 .github/workflows/gradle.yml 파일을 편집하고 저장할 수 있는 창이&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;열리게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1725&quot; data-origin-height=&quot;1130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dE960s/btsFXH1rXoA/rZDKrrlWm5PU8kMzxyiHfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dE960s/btsFXH1rXoA/rZDKrrlWm5PU8kMzxyiHfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dE960s/btsFXH1rXoA/rZDKrrlWm5PU8kMzxyiHfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdE960s%2FbtsFXH1rXoA%2FrZDKrrlWm5PU8kMzxyiHfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1725&quot; height=&quot;1130&quot; data-origin-width=&quot;1725&quot; data-origin-height=&quot;1130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서 윗 부분만 기본적으로 설명하자면 아래와 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 yml 파일은 공백을 따라 인식하니 주의해서 작성, 수정 해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1711073313864&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: Java CI with Gradle # CI 이름

on:  # 언제 시작할건가
  push: # push 될 때
    branches: [ &quot;main&quot; ] # main branch에
  pull_request: # pull_request가 열릴 때
    branches: [ &quot;main&quot; ]  # main branc로
    
runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 17 
      uses: actions/setup-java@v4
      with:
        java-version: '17' ## java 버전에 맞게 수정
        distribution: 'temurin'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음은 빌드에 필요한 것들이 있다면 부가적으로 설정 가능하다,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gradlew 권한 부여와 서버에 필요한 key.properties를 만들도록 추가할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1711088766639&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; - name: Create keys.properties file
        run: | 
          echo url=${{ secrets.DATABASE_URL }} &amp;gt; src/main/resources/keys.properties
          echo username=${{ secrets.DATABASE_USERNAME }} &amp;gt;&amp;gt; src/main/resources/keys.properties
          echo password=${{ secrets.DATABASE_PASSWORD }} &amp;gt;&amp;gt; src/main/resources/keys.properties

- name: Grant Execute Permission to Gradlew
       run: chmod +x ./gradlew&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 정보들은 GitHub의 secrets를 이용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트의 상단 카테고리 중 settings를 누르고 들어가 등록해주면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1351&quot; data-origin-height=&quot;921&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GRT24/btsF1uMQTVg/OFyzeI7pdy0sMKnRbaZo4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GRT24/btsF1uMQTVg/OFyzeI7pdy0sMKnRbaZo4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GRT24/btsF1uMQTVg/OFyzeI7pdy0sMKnRbaZo4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGRT24%2FbtsF1uMQTVg%2FOFyzeI7pdy0sMKnRbaZo4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;781&quot; height=&quot;921&quot; data-origin-width=&quot;1351&quot; data-origin-height=&quot;921&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제부터 github-action에서 쓰일 비밀번호나 키와 같은 가려져야하는 항목들은 이곳에 등록해서 사용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 나올 모든 secrets.xxx는 다 이곳에 등록된 키 값들이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 빌드와 유닛 테스트 설정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드와 동시에 test를 실행하고 싶다면 ./gradlew build로 두면 되고, test와 build를 분리하고 싶다면 아래와 같이&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분리하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트와 빌드를 분리하는 것은 정확히 어떤 스텝에서 문제가 생겼는지 판단 할 때 유용하게 쓰인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&amp;nbsp; 빌드와 테스트가 완료된다면 도커 이미지로 빌드하고 NCP Container Registry에 이미지를 업로드 하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그는 고유값을 가지도록 github.sha를 이용했다.&lt;/p&gt;
&lt;pre id=&quot;code_1711089232891&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- name: Setup Gradle
  uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

- name: Build with Gradle Wrapper
  run: ./gradlew build -x test

- name: Run Unit Tests
  run: ./gradlew test

- name: NCP Container Registry push
   run: |
      echo &quot;${{ secrets.API_PASSWORD }}&quot; | docker login ${{ secrets.NCP_CONTAINER_URL }} --username ${{ secrets.API_KEY_ID }} --password-stdin
      docker build -t ${{ secrets.NCP_CONTAINER_URL }}/melody-market:${{ github.sha }} .
      docker push ${{ secrets.NCP_CONTAINER_URL }}/melody-market:${{ github.sha }}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 필요한 키 값들은&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1711089944410&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편&quot; data-og-description=&quot;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는 &quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/42&quot; data-og-url=&quot;https://elephant-dev.tistory.com/42&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Sylof/hyVAAS167q/EuaiimVlMHBF3kEm1x62JK/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/fNHWi/hyVDIPokCw/JQJv0nVB4yPjsMUaFXHt41/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/bMi99M/hyVAzmiI7x/HOzanMSil1weYvCydagUSk/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/42&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/42&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Sylof/hyVAAS167q/EuaiimVlMHBF3kEm1x62JK/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/fNHWi/hyVDIPokCw/JQJv0nVB4yPjsMUaFXHt41/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/bMi99M/hyVAzmiI7x/HOzanMSil1weYvCydagUSk/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 포스트에 아래 부분을 확인하면 된다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;1259&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PH7nE/btsF0ahq7H2/XtHmj88CqKXKrBcMllmWh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PH7nE/btsF0ahq7H2/XtHmj88CqKXKrBcMllmWh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PH7nE/btsF0ahq7H2/XtHmj88CqKXKrBcMllmWh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPH7nE%2FbtsF0ahq7H2%2FXtHmj88CqKXKrBcMllmWh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;577&quot; height=&quot;1259&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;1259&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 그래프로 표현하는 부분이니 수정하지 않도록 하겠다.&lt;/p&gt;
&lt;pre id=&quot;code_1711090055447&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; dependency-submission:

    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies.
      # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md
      - name: Generate and submit dependency graph
        uses: gradle/actions/dependency-submission@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 정말 오류가 많이 나서 힘들었었던.. deploy 부분이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711090138471&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
        - name: SSH and Deploy to Kubernetes
          uses: appleboy/ssh-action@master
          with:
            host: ${{ secrets.SERVER_HOST }}
            username: ${{ secrets.SERVER_USERNAME }}
            key: ${{ secrets.NCP_KEYFILE }}
            script: |
              echo &quot;${{ secrets.API_PASSWORD }}&quot; | docker login ${{ secrets.NCP_CONTAINER_URL }} --username ${{ secrets.API_KEY_ID }} --password-stdin
              # Kubernetes 배포 명령 실행
              export NCLOUD_ACCESS_KEY=${{ secrets.NCLOUD_ACCESS_KEY }}
              export NCLOUD_SECRET_KEY=${{ secrets.NCLOUD_SECRET_KEY }}
              export NCLOUD_API_GW=https://ncloud.apigw.ntruss.com
              export NCLOUD_PROFILE=project
              export PATH=$PATH:$HOME/bin
              kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot; set image deployment/melody-deployment melody=melody.kr.ncr.ntruss.com/melody-market:${{ github.sha }} --record
              # 배포 상태 확인 및 롤백 처리
              if ! kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot; rollout status deployment/melody-deployment --timeout=60s; then
                echo &quot;Deployment failed, starting rollback...&quot;
                kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot; rollout undo deployment/melody-deployment
                echo &quot;Rollback completed.&quot;
              else
                echo &quot;Deployment succeeded.&quot;
              fi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘못 설정 시 문제가 생길 여지가 많은 부분이므로 하나씩 설명하겠다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ssh로 kubectl이 설치된 서버에 접속해서 deploy 하도록 하는 스크립트이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 with절을 보면 접속할 서버의 IP와 Username과 Keyfile을 제공해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 클래식을 사용하고있는 사람들이라면 서버 접속 전용 IP와 port를 제공해야하며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VPC 사용자라면 public IP로 포트 없이 접속하면 된다 ssh 접속 포트인 22번을 사용하게되기 때문이다.&lt;/p&gt;
&lt;pre id=&quot;code_1711090395359&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;          with:
            host: ${{ secrets.SERVER_HOST }}
            username: ${{ secrets.SERVER_USERNAME }}
            key: ${{ secrets.NCP_KEYFILE }}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 NCP_KEYFILE이란? 서버에서 ssh 접속 가능하도록 설정해주어야한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 eploy를 실행하려는 NCP 서버에 접속해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 아래와 같은 명령어를 수행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1711091501805&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;openssl genrsa -out ssh_key.pem 4096
chmod 600 ssh_key.pem
mkdir .ssh
ssh-keygen -y -f ssh_key.pem &amp;gt; .ssh/authorized_keys
chmod 700 .ssh
chmod 600 .ssh/authorized_keys
systemctl restart sshd&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 작업은 root로 수행 했고, root로 접속해서 deploy할것이라 다른 계정에 대한 내용은 없으니 주의하여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 계정으로 수행하는 경우 해당 계정에서 수행해 주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 ssh_key.pem을 vi로 열어 내용을 복사해서 github secret에 넣어주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 내용이 위에 key: ${{ secrets.NCP_KEYFILE }}에 해당 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 서버에 접속해서 수행할 deploy script 작성 부분이다.&lt;/p&gt;
&lt;pre id=&quot;code_1711091737707&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; script: |
              echo &quot;${{ secrets.API_PASSWORD }}&quot; | docker login ${{ secrets.NCP_CONTAINER_URL }} --username ${{ secrets.API_KEY_ID }} --password-stdin
              # Kubernetes 배포 명령 실행
              export NCLOUD_ACCESS_KEY=${{ secrets.NCLOUD_ACCESS_KEY }}
              export NCLOUD_SECRET_KEY=${{ secrets.NCLOUD_SECRET_KEY }}
              export NCLOUD_API_GW=https://ncloud.apigw.ntruss.com
              export NCLOUD_PROFILE=project
              export PATH=$PATH:$HOME/bin
              kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot; set image deployment/melody-deployment melody=melody.kr.ncr.ntruss.com/melody-market:${{ github.sha }} --record
              # 배포 상태 확인 및 롤백 처리
              if ! kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot; rollout status deployment/melody-deployment --timeout=60s; then
                echo &quot;Deployment failed, starting rollback...&quot;
                kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot; rollout undo deployment/melody-deployment
                echo &quot;Rollback completed.&quot;
              else
                echo &quot;Deployment succeeded.&quot;
              fi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 내가 작성한 포스트를 따라 여기까지 왔다면 위의 설정값이 모두 맞을지 모르지만 그게 아니라면&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자신의 환경에 맞게 수정해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bash에 작성된 환경 설정들이 ssh 접속 시 반영되지 않기 때문에 꼭 필요한 것들을 다 export 해주고 시작해야 에러 없이&amp;nbsp;&lt;br /&gt;잘 진행되므로 위와 같이 자신에 환경에 필요한 export를 해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 부분을 설정해주지 않아 여러가지 에러가 발생해서 고생했었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 방법외에 NCP에서 제공하는 sourceBuild와 sourceDeploy를 활용해서 배포가 가능하긴 하지만 비용적인 절약을 위해&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;직접 ssh로 붙어 빌드된 image를 배포하는 형태를 채택하였다.&lt;/p&gt;</description>
      <category>Git hub</category>
      <category>github action</category>
      <category>github action kubernetes</category>
      <category>github action ncloud kubernetes service</category>
      <category>github action ncp</category>
      <category>github action rolling update</category>
      <category>github action ssh 접속</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/43</guid>
      <comments>https://elephant-dev.tistory.com/43#entry43comment</comments>
      <pubDate>Fri, 22 Mar 2024 16:19:59 +0900</pubDate>
    </item>
    <item>
      <title>[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편</title>
      <link>https://elephant-dev.tistory.com/42</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진행해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;*pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는 과정도 작성되어있으니 같은 문제가 발생한다면 참고하여 해결하는데 도움이 될 수 있을 것 이다!*&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1편에서는 서버 생성과 vpc 생성, kubernetes 생성 및 Container Registry 생성 방법에 대해 작성했으니&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고하면 된다.&lt;/p&gt;
&lt;figure id=&quot;og_1710830509287&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편&quot; data-og-description=&quot;프로젝트를 진행하면서, 롤링 업데이트 배포 전략을 사용하기 위해 NCP에서 제공해주는 쿠버네티스를 이용해 보았다. 진행 중에 내 입맞에 맞는 알맞는 가이드를 잘 못찾아서 해결하느라 정말 &quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/41&quot; data-og-url=&quot;https://elephant-dev.tistory.com/41&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bykS94/hyVDHoTYmq/QLfty22BppHx8b4u74ej71/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/fDpW9/hyVDB936nL/eidad7L2kaXd7GC1yDWR11/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/0IiRL/hyVDFYVeeh/eG0gJEAMYmXSjG1O1Q2bjk/img.png?width=669&amp;amp;height=690&amp;amp;face=0_0_669_690&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/41&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/41&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bykS94/hyVDHoTYmq/QLfty22BppHx8b4u74ej71/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/fDpW9/hyVDB936nL/eidad7L2kaXd7GC1yDWR11/img.png?width=800&amp;amp;height=501&amp;amp;face=0_0_800_501,https://scrap.kakaocdn.net/dn/0IiRL/hyVDFYVeeh/eG0gJEAMYmXSjG1O1Q2bjk/img.png?width=669&amp;amp;height=690&amp;amp;face=0_0_669_690');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트를 진행하면서, 롤링 업데이트 배포 전략을 사용하기 위해 NCP에서 제공해주는 쿠버네티스를 이용해 보았다. 진행 중에 내 입맞에 맞는 알맞는 가이드를 잘 못찾아서 해결하느라 정말&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 클러스터와 상호작용 하기 위해 만들어 두었던 서버에 접속해서 pod 생성을 해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 서버 생성시 사용했던 인증키 (xxx.pem 파일)을 드래그해서 관리자 비밀번호를 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;1049&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AieGb/btsFWiZL3Dn/0ZwFKRK6BfVzvBpBi2vn7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AieGb/btsFWiZL3Dn/0ZwFKRK6BfVzvBpBi2vn7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AieGb/btsFWiZL3Dn/0ZwFKRK6BfVzvBpBi2vn7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAieGb%2FbtsFWiZL3Dn%2F0ZwFKRK6BfVzvBpBi2vn7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;593&quot; height=&quot;1049&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;1049&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 비밀번호를 통해 ssh 접속을 시도하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ssh root@공인IP&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속해서 출력된 비밀번호 입력하여 접속하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 접속에 성공했다면 이제 도커와 kubectl을 설치 해야 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;1. docker 설치&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈디렉터리에서 작업을 시작할 것이므로 홈 디렉터리로 이동한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710830962344&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커를 설치하기 위해 도커 Yum 레포지토리를 등록한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710831022120&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커를 설치한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710831048460&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yum install docker-ce docker-ce-cli containerd.io -y&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커 서비스를 시작하고 서버 재 구동 시 자동으로 도커가 시작될 수 있도록 설정한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710831166260&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;systemctl start docker
systemctl enable docker&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 경우, 이미 컨테이너 레지스트리에 도커 이미지를 올려놓은 상태이므로 참고하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레지스트리에 도커 이미지를 업로드 하는 방법에 대해서는 이후 추가 포스팅 하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 도커에 로그인 해야하는데 이전에 만들었던 Container Registry에 출력되었던 login 방법을 수행하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1313&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4OGz4/btsFUFuGpCm/NsI8rkYQcmg5K3FXWYTJGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4OGz4/btsFUFuGpCm/NsI8rkYQcmg5K3FXWYTJGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4OGz4/btsFUFuGpCm/NsI8rkYQcmg5K3FXWYTJGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4OGz4%2FbtsFUFuGpCm%2FNsI8rkYQcmg5K3FXWYTJGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1313&quot; height=&quot;392&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1313&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 부분을 복사해서 입력하면 key를 입력하라고 할 것 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 키를 발급받아야 하는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계정 관리 탭에 들어가 API 인증키를 발급 받거나, 이미 있다면 해당 Key와 Secret Key를 이용하여 로그인 하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;713&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zx7Sr/btsFT0F89Ch/9JCW04QKNGTItw3weblYZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zx7Sr/btsFT0F89Ch/9JCW04QKNGTItw3weblYZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zx7Sr/btsFT0F89Ch/9JCW04QKNGTItw3weblYZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzx7Sr%2FbtsFT0F89Ch%2F9JCW04QKNGTItw3weblYZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;808&quot; height=&quot;713&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;713&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;push할 이미지가 있다면 미리 registry에 push 해 놓으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;2. Kubectl, ncp-iam-authenticator 설치&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최신 버전의 kubectl 바이너리를 다운로드 한다. 시간이 좀 소요될 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1710831702471&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -LO &quot;https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드한 kubectl을 설치하고 파일의 권한을 수정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 root로 접속했기 때문에 sudo 명령어 없이 그냥 진행해주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1710831793699&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치를 완료하고 잘 설치 되었는지 클라이언트 버전 확인 명령어를 통해 버전이 잘 출력되는지 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710831848408&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl version --client&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;91&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m5xgv/btsFR07FeOl/0lUd6oTdH0kPUEZ9IhwdOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m5xgv/btsFR07FeOl/0lUd6oTdH0kPUEZ9IhwdOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m5xgv/btsFR07FeOl/0lUd6oTdH0kPUEZ9IhwdOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm5xgv%2FbtsFR07FeOl%2F0lUd6oTdH0kPUEZ9IhwdOK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;733&quot; height=&quot;91&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;91&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 ncp-iam-autentication 바이너리 파일을 네이버 클라우드에서 다운로드 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710831942556&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -o ncp-iam-authenticator https://kr.object.ncloudstorage.com/nks-download/ncp-iam-authenticator/v1.0.0/linux/amd64/ncp-iam-authenticator&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드가 완료되었다면 chmod 명령어를 통해 실행 권한을 추가하고 바이너리를 복사해서 생성한다&lt;/p&gt;
&lt;pre id=&quot;code_1710831988626&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;chmod +x ./ncp-iam-authenticator &amp;amp;&amp;amp; mkdir -p /root/bin &amp;amp;&amp;amp; cp ./ncp-iam-authenticator /root/bin/ncp-iam-authenticator&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 Bash 프로파일에 위에서 만든 bin폴더를 path에 추가하여 바라볼 수 있도록 해준다&lt;/p&gt;
&lt;pre id=&quot;code_1710832093715&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;echo 'export PATH=$PATH:HOME/bin' &amp;gt;&amp;gt; ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 새로 적용한 bash_profile을 적용할 수 있도록 아래 중 한가지를 입력하여 재 적용 해준다&lt;/p&gt;
&lt;pre id=&quot;code_1710832135367&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;. ~/.bash_profile
source ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ncp-iam-autentication가 제대로 설치되었는지 help 명령어를 통해 잘 출력되는지 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710832384857&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ncp-iam-authenticator help&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1145&quot; data-origin-height=&quot;499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d7ZltM/btsFR25vrrc/VpQ0sY09YrSTVSTSnJRO81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d7ZltM/btsFR25vrrc/VpQ0sY09YrSTVSTSnJRO81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d7ZltM/btsFR25vrrc/VpQ0sY09YrSTVSTSnJRO81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd7ZltM%2FbtsFR25vrrc%2FVpQ0sY09YrSTVSTSnJRO81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1145&quot; height=&quot;499&quot; data-origin-width=&quot;1145&quot; data-origin-height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 IAM Autentication 설정 파일을 생성하고 편집진행해야한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 커맨드 순서대로 진행해서 파일과 폴더를 생성해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1710832834997&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir ~/.ncloud: ~/.ncloud
vi ~/.ncloud/configure&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 configure파일에 위에서 확인했던 API key를 작성하고 esc -&amp;gt; :wq를 통해 저장하고 나온다&lt;/p&gt;
&lt;pre id=&quot;code_1710833152679&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[DEFAULT]
ncloud_access_key_id=&amp;lt;Access key&amp;gt;
ncloud_secret_access_key=&amp;lt;Secret Key&amp;gt;
ncloud_api_url=https://ncloud.apigw.ntruss.com

[project]
ncloud_access_key_id=&amp;lt;Access key&amp;gt;
ncloud_secret_access_key=&amp;lt;Secret Key&amp;gt;
ncloud_api_url=https://ncloud.apigw.ntruss.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 .bash_profile을 열어 NCLOUD API 키 관련 설정값을 추가해 줄 것이다&lt;/p&gt;
&lt;pre id=&quot;code_1710832485683&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vi ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음의 내용을 .bash_profile의 맨 끝에 위에서 확인했던 API Key를 올바르게 기입해서 추가해주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1710832665104&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NCLOUD_ACCESS_KEY=&amp;lt;Access Key&amp;gt;
NCLOUD_SECRET_KEY=&amp;lt;Secret Key&amp;gt;
NCLOUD_API_GW=https://ncloud.apigw.ntruss.com
NCLOUD_PROFILE=project&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 IAM Authenticator를 사용해 Kubernetes의 kubeconfig 파일을 생성해 주면 된다&lt;/p&gt;
&lt;pre id=&quot;code_1710833224601&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ncp-iam-authenticator create-kubeconfig --region KR --clusterUuid &amp;lt;kubernetes uuid&amp;gt; &amp;gt; kubeconfig.yml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 커맨드에서 필요로하는 cluster uuid는 ncp 페이지의 Ncloud Kubernetes Service에 클러스터 uuid를 입력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;kubernetes uuid&amp;gt; 이 부분을 치환해서 넣고 그 옆 &amp;gt; 꺽쇠는 살려두어야 yml파일 생성되니 주의하자!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1620&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hr2dt/btsFUdFnF9n/MO5llWYKnHzGal0OtuAom1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hr2dt/btsFUdFnF9n/MO5llWYKnHzGal0OtuAom1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hr2dt/btsFUdFnF9n/MO5llWYKnHzGal0OtuAom1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHr2dt%2FbtsFUdFnF9n%2FMO5llWYKnHzGal0OtuAom1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1620&quot; height=&quot;682&quot; data-origin-width=&quot;1620&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빨간색 복사 버튼을 눌러 클러스터 uuid를 가져오면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 생성된 kubeconfig 파일을 이용하여 쿠버네티스 클러스터의 네임스페이스를 조회했을 시 잘 출력된다면 잘 연결 되었음을 알 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1710834056093&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get namespaces --kubeconfig kubeconfig.yml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 bash_profile을 열어 kubeconfig 파일을 사용해 kubectl 명령어를 사용할 수 있도록 alias를 걸어준다.&lt;/p&gt;
&lt;pre id=&quot;code_1710834114069&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;alias kubectl='kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot;'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료가 되었다면 다시 .bash_profile 적용을 위해 두 명령어 중 한가지를 수행하여 수정된 프로파일을 적용해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1710834220082&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;. ~/.bash_profile
source ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커의 레지스트리 접근정보를 사용해 쿠버테시트 시크릿을 생성한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710836557069&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create secret docker-registry regcred 
--docker-server=&amp;lt;Contaner registry public Endpoint&amp;gt; --docker-username=&amp;lt;사용자의 Access key&amp;gt; 
--docker-password=&amp;lt;Secret Key&amp;gt; --docker-email=&amp;lt;ncp 계정메일&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성이 완료되었다면 적용이 잘 되었는지 다음 명령어를 통해 시크릿 목록을 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710836781590&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get secret&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;85&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d4Y3Tr/btsFUmWyf2N/equssTlwqfEI4ul0KjFkL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d4Y3Tr/btsFUmWyf2N/equssTlwqfEI4ul0KjFkL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d4Y3Tr/btsFUmWyf2N/equssTlwqfEI4ul0KjFkL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd4Y3Tr%2FbtsFUmWyf2N%2FequssTlwqfEI4ul0KjFkL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;85&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;85&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 출력이 잘 되면 잘 생성 된 것 이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 파드들을 띄우기 위한 설정을 진행할 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 pod를 직접 실행시키기 위한 pod.yaml, deployment를 생성하기 위한 deployment.yaml과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스를 등록하기 위한 service.yaml을 구성하는 예시를 작성하겠으나 실제로 서버에는 deployment와 서비스만 등록하여&lt;br /&gt;사용할 예정이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;pod란?&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod는 kubernetes에서 애플리케이션의 가장 실행 단위를 말하며 컨테이너의 그룹을 실행하는 단위이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나 이상의 컨테이너를 포함할 수 있으며, 이 컨테이너들은 저장소와 네트워킹을 공유한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 pod는 고유한 IP주소를 가지며 kubernetes 클러스터 내에서 스케줄링되어 실행 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;Deployment란?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod의 상태를 선언적으로 관리하는 리소스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod를 3개 실행하고 싶다면 이를 선언하고 Deployment 사용하여 선언하고 관리하게 할 수 있다.&lt;br /&gt;Deployment는 pod들을 직접 관리하고 제어하는데 사용되기 때문에 kubernetes가 지정된 상태를 유지하도록 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 이미지를 사용하는 pod 복제본 수를 정의하고, 이 상태를 유지하려면 Deployment 리소스를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Deployment는 pod의 생성, 삭제, 업데이트를 관리하여 지정된 상태를 유지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때문에 나는 Deployment로 pod를 2개 생성해서 관리하게 하는 yaml파일을 작성하고 사용하려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 node를 2개 만들었는데 node 2개에 2개의 pod를 두는 것 즉, node의 개수와 pod의 개수가 일치하거나 더 많게 설정하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고가용성이ㅣ 중요한 상황에서는 효율성에 문제가 있을 수 있어 권장되지는 않는 방법이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이번에는 서버 비용 문제와 공부 목적에 더 의의를 두고 2개의 노드와 2개의 pod를 생성해보려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 서버를 구성하기 위한 목적을 두고 있다면 애플리케이션 요구사항과 클러스터 리소스를 균형있게 고려해서 설계 후 적용하여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1710851306022&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vi ~/.pod.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod.yaml 작성&lt;/p&gt;
&lt;pre id=&quot;code_1710851183013&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: debug-pod
spec:
  containers:
  - name: debug-container
    image: busybox
    command: ['sh', '-c', 'env']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 디버깅을 위해 환경을 출력하는 pod의 예시이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정해서 파드가 running 상태일 때 pod의 로그를 확인하여 환경 정보들을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 애플리케이션을 pull받아서 직접 파드로 올리도록 구성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위에서 언급했듯이, deployment를 이용해서 pod를 생성할 것이기 때문에 그 작업은 deployment.yaml에서 진행하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod.yaml을 작성한 후 다음과 같이 적용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1710851370758&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f pod.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 pod가 실행되고 있는지 목록을 조회하여 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710851409499&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pods&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-19 오후 9.31.17.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q9ZAR/btsFUn2ogvS/vo3TxNUMJEWiq3mnxvaKn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q9ZAR/btsFUn2ogvS/vo3TxNUMJEWiq3mnxvaKn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q9ZAR/btsFUn2ogvS/vo3TxNUMJEWiq3mnxvaKn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ9ZAR%2FbtsFUn2ogvS%2Fvo3TxNUMJEWiq3mnxvaKn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1060&quot; height=&quot;104&quot; data-filename=&quot;스크린샷 2024-03-19 오후 9.31.17.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;status가 completed인 것으로 보아 잘 실행된 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 설명한 것 처럼 환경변수 출력이 잘 되었는지 로그도 확인해보자&lt;/p&gt;
&lt;pre id=&quot;code_1710851581676&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl logs debug-pod&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;debug-pod 이부분은 여러분이 사용한 pod이름을 입력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-19 오후 9.34.16.png&quot; data-origin-width=&quot;1008&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJEWxm/btsFR2klMCm/ilkrHR2aq6xJiYZbF9HAk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJEWxm/btsFR2klMCm/ilkrHR2aq6xJiYZbF9HAk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJEWxm/btsFR2klMCm/ilkrHR2aq6xJiYZbF9HAk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJEWxm%2FbtsFR2klMCm%2FilkrHR2aq6xJiYZbF9HAk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;611&quot; height=&quot;720&quot; data-filename=&quot;스크린샷 2024-03-19 오후 9.34.16.png&quot; data-origin-width=&quot;1008&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 출력되고 있는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 여기서 커맨드 입력이 너무 번거로우므로 kubectl 자동완성을 사용해 볼 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1710851809380&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;source /usr/share/bash-completion/bash_completion&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 명령어를 통해 bash-completion을 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음엔 시스템 전체에 적용되도록 설정하자.&lt;/p&gt;
&lt;pre id=&quot;code_1710851874360&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl &amp;gt; /dev/null&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 여기에서 추가로 kubectl에 대한 alias가 존재하므로 더 간결하게 수정하고 적용해보겠다.&lt;/p&gt;
&lt;pre id=&quot;code_1710852124273&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;echo 'alias k=kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot;' &amp;gt;&amp;gt; ~/.bashrc
echo 'complete -o default -F __start_kubectl k' &amp;gt;&amp;gt;~/.bashrc
exec bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 kub까지만 치고 탭키를 눌러보면 커맨드들이 자동 완성 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 편리해진 상태로 이제 service를 등록해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vi melody-service.yaml&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 서비스 yaml파일 이름을 이렇게 했지만 자유롭게 수정해도 무방하다.&lt;/p&gt;
&lt;pre id=&quot;code_1710852300143&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kind: Service
apiVersion: v1
metadata:
  name: melody-service
spec:
  ports:
  - port: 80
    targetPort: 9090
  selector:
    app: melody
  type: LoadBalancer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서 service name과 원하는 포트를 기입해서 수정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스도 적용해보자&lt;/p&gt;
&lt;pre id=&quot;code_1710852393412&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f service.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 중인 서비스를 확인해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1710852412171&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get service&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-19 오후 10.48.18.png&quot; data-origin-width=&quot;1950&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAwa1u/btsFWsO7Pw2/wEkkwWr9fDvzK7j9K4WTo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAwa1u/btsFWsO7Pw2/wEkkwWr9fDvzK7j9K4WTo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAwa1u/btsFWsO7Pw2/wEkkwWr9fDvzK7j9K4WTo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAwa1u%2FbtsFWsO7Pw2%2FwEkkwWr9fDvzK7j9K4WTo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1950&quot; height=&quot;134&quot; data-filename=&quot;스크린샷 2024-03-19 오후 10.48.18.png&quot; data-origin-width=&quot;1950&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 아래와 같이 connection refuse가 뜬다면 아까 적용한 bash-completion 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vi ~/.bashrc 커맨드를 입력해 아래와 같이 수정하자&lt;/p&gt;
&lt;pre id=&quot;code_1710856432752&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#alias k=kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot; 잘못 기입된 것 아래와 같이 수정필요
alias k='kubectl --kubeconfig=&quot;/root/kubeconfig.yml&quot;'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 적용한 후 kubectl 대신 k로 조회하자&lt;/p&gt;
&lt;pre id=&quot;code_1710856474074&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;exec bash
k get service&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로는 kubectl 커맨드를 적용한 alias k로 입력하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용하지 않은 경우 k 대신 kubectl을 사용하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1710856875252&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vi ~/melody-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: melody-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: melody
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: melody
    spec:
      containers:
      - name: melody
        image: 레지스트리 public endpoint/melody-market:1.0v
        ports:
        - containerPort: 9090
        env:
        - name: SPRING_DATASOURCE_URL
          value: &quot;jdbc:mysql://1xx.xxx.xxx.xxx:포트/db명?characterEncoding=utf8&amp;amp;useSSL=false&quot;
        - name: SPRING_DATASOURCE_USERNAME
          value: &quot;유저네임&quot;
        - name: SPRING_DATASOURCE_PASSWORD
          value: &quot;비밀번호&quot;
        - name: SPRING_REDIS_HOST
          value: &quot;호스트IP&quot;
        - name: SPRING_REDIS_PORT
          value: &quot;포트&quot;
      imagePullSecrets:
      - name: regcred&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인에 따라 다르겠지만 롤링 업데이트 배포전략 적용을 위해 전략 설정을 롤링 업데이트로 기입해주었고 -- 옵션사항,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;containers는 Container Registry에 업로드&amp;nbsp; 된 도커 이미지를 pull받아 사용하도록 했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;env도 역시 옵션사항인데 나의 경우 pod내부에 애플리케이션이 실행 될 때 필요한 환경 정보들을 기입해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deployment 도 적용 해보자&lt;/p&gt;
&lt;pre id=&quot;code_1710857055042&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- alias를 적용한 경우 커맨드
k apply -f melody-deploy.yaml

-- alias 적용하지 않은 경우
kubectl apply -f melody-deploy.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 deployment가 잘 적용 되었는지 확인해보자&lt;/p&gt;
&lt;pre id=&quot;code_1710857163539&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- alias 적용 한 경우
k get pods

-- alias 적용하지 않은 경우
kubectl get pods&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-19 오후 11.05.34.png&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wHCGF/btsFR3DDcd1/IWKc97TS6l9UXQzKhoc4f1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wHCGF/btsFR3DDcd1/IWKc97TS6l9UXQzKhoc4f1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wHCGF/btsFR3DDcd1/IWKc97TS6l9UXQzKhoc4f1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwHCGF%2FbtsFR3DDcd1%2FIWKc97TS6l9UXQzKhoc4f1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1054&quot; height=&quot;130&quot; data-filename=&quot;스크린샷 2024-03-19 오후 11.05.34.png&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 적용했던 pod가 나오지 않는 이유는 지웠다! 필요없기 때문에.. 그리고 환경 변수만 확인하는 pod라 아마 CrashLoopBackOff&amp;nbsp;&lt;br /&gt;발생했을 것 이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod 삭제는 다음과 같이 하면 된다&lt;/p&gt;
&lt;pre id=&quot;code_1710857265547&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- alias 적용 한 경우
k delete pods &amp;lt;pod이름&amp;gt;

-- alias 적용하지 않은 경우
kubectl delete pods &amp;lt;pod이름&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 deployment 또는 pod 내가 겪었던 문제 기준으로 문제 발생 시 해결 방법에 대해 추가 설명 하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 발생 내용은 다음과 같은 커맨드를 통해 log를 확인할 수 있다&lt;/p&gt;
&lt;pre id=&quot;code_1710858077709&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- alias 적용한 경우
k logs &amp;lt;pod 또는 deployment 이름&amp;gt;

-- alias 적용하지 않은 경우
kubectl logs &amp;lt;pod 또는 deployment 이름&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;발생 문제 1.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Status가 imagePull에러가 발생한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;해결 방법 &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 이미지를 pull 받아오기 위한 Container Registry에 yaml에 기입한 내용과 동일한 이미지 이름을 기입했는가? 확인해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;public endpoint 혹은 private endpoint를 올바르게 기입했는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. kubectl create secret 생성 시 올바른 정보를 기입한 것이 맞는가?? 내 API KEY와 Secret key와 계정 이메일을 올바르게 기입한게 맞는지 반드시 확인해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Container Registry로 통신이 나가는지 ping 테스트 해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ping &amp;lt;public endpoint&amp;gt; 시도 시 잘 수행되는지 체크해보아야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 서브 계정으로 수행중이라면 서브 계정에 권한을 부여했는가? 체크해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;발생 문제 2.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;web server를 구성했는데 ncp에 구성한 데이터 베이스 서버 혹은 다른 서버로 접속이 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;해결 방법&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 접속하고자 하는 서버에 접속이 잘 되는지 확인해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;curl -v IP:PORT 입력해서 connection이 성공하는지 확인해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 안되는 경우 해당 서버에서 ACG에 현재 서버 IP와 Port를 인바운드 규칙에 추가해 주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 1번은 잘 수행되는데 pod 내부에서 안되는 것 같은 경우 deploy.yaml에 접속한 정보들이 정말 올바르게 쓰여있는지 확인하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 2번까지 모두 성공했을 시 pod가 timeout이 발생하며 죽기 전까지 순식간에 파드 내부로 접속해서 curl -v 명령어를 통해 확인해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커맨드 순서는 아래와 같으며 반드시 Status가 Running 상태일 때 수행해야한다. 죽기전 그 순간을 노려서 접속해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1710857978585&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- alias 적용한 경우
k exec -it &amp;lt;deploy이름&amp;gt; -c &amp;lt;컨테이너 이름&amp;gt; -- /bin/bash

-- alias 적용하지 않은 경우
kubectl exec -it &amp;lt;deploy이름&amp;gt; -c &amp;lt;컨테이너 이름&amp;gt; -- /bin/bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deployment가 실패할 경우 다시 재 시작하기 때문에 살아날 때 까지 나의 경우 계속 반복해서 순간을 노리기 위해 해당 커맨드를 날렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 curl -v IP:PORT 명령어를 날려 확인하자&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이 부분에서 원인을 파악했고 해결하기 위해 노드들의 IP를 접속하고자하는 서버의 ACG에 인바운드 규칙으로 넣어줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드 IP 확인 방법&lt;/p&gt;
&lt;pre id=&quot;code_1710858166260&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- alias 적용한 경우
k get nodes -o wide

-- alias 적용하지 않은 경우
kubectl get nodes -o wide&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력된 노드의 IP 중 External IP와 필요한 port를 넣으면 다음 deployment 시도 시 정상화 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 자세한 서버 통신 방법을 확인하고 싶다면 아래의 포스트를 확인하자.&lt;/p&gt;
&lt;figure id=&quot;og_1710858259455&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Linux] 서버 간 통신 테스트 방법&quot; data-og-description=&quot;# 접속 성공ㅇ Linux 서버에서 개발을 진행 할 때 서버 간 통신이 필요한 경우가 많다. 이 때 내가 통신하고 싶은 서버와 포트로 통신이 가능한지 테스트 하는 방법을 정리 해보았다. - TELNET telent &quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/34&quot; data-og-url=&quot;https://elephant-dev.tistory.com/34&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bjxKOu/hyVDAXHyja/HkBqHaWO40Zqs0DOSxYcG1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/hCBp1/hyVDDUqi5j/M9x4Hd5q10SOTP6sApBewK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dNawot/hyVABRvg6B/Ru2OkKJetIdvJ2fMwNSpu1/img.jpg?width=472&amp;amp;height=472&amp;amp;face=0_0_472_472&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/34&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/34&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bjxKOu/hyVDAXHyja/HkBqHaWO40Zqs0DOSxYcG1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/hCBp1/hyVDDUqi5j/M9x4Hd5q10SOTP6sApBewK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dNawot/hyVABRvg6B/Ru2OkKJetIdvJ2fMwNSpu1/img.jpg?width=472&amp;amp;height=472&amp;amp;face=0_0_472_472');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Linux] 서버 간 통신 테스트 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;# 접속 성공ㅇ Linux 서버에서 개발을 진행 할 때 서버 간 통신이 필요한 경우가 많다. 이 때 내가 통신하고 싶은 서버와 포트로 통신이 가능한지 테스트 하는 방법을 정리 해보았다. - TELNET telent&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 까지 한 후 load blancer의 접속 정보로 접속해보면 web서버인 경우 잘 접속되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2024-03-19 오후 11.26.54.png&quot; data-origin-width=&quot;1972&quot; data-origin-height=&quot;1406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mho8t/btsFUBzoteA/Sux8HRzgjwl34JFM8ABTUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mho8t/btsFUBzoteA/Sux8HRzgjwl34JFM8ABTUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mho8t/btsFUBzoteA/Sux8HRzgjwl34JFM8ABTUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmho8t%2FbtsFUBzoteA%2FSux8HRzgjwl34JFM8ABTUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1972&quot; height=&quot;1406&quot; data-filename=&quot;edited_스크린샷 2024-03-19 오후 11.26.54.png&quot; data-origin-width=&quot;1972&quot; data-origin-height=&quot;1406&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2024-03-19 오후 11.27.26.png&quot; data-origin-width=&quot;1393&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m8WNL/btsFWLHGFdl/Dm319z2J4yHWWKoK2T2sW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m8WNL/btsFWLHGFdl/Dm319z2J4yHWWKoK2T2sW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m8WNL/btsFWLHGFdl/Dm319z2J4yHWWKoK2T2sW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm8WNL%2FbtsFWLHGFdl%2FDm319z2J4yHWWKoK2T2sW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1393&quot; height=&quot;702&quot; data-filename=&quot;edited_스크린샷 2024-03-19 오후 11.27.26.png&quot; data-origin-width=&quot;1393&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud Platform/Naver Cloud</category>
      <category>kubectl</category>
      <category>NCP kubernetes</category>
      <category>NCP 서버간 통신</category>
      <category>ncp 쿠버네티스 외부 통신</category>
      <category>pod 통신 안됨</category>
      <category>네이버클라우드 쿠버네티스</category>
      <category>쿠버네티스 에러</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/42</guid>
      <comments>https://elephant-dev.tistory.com/42#entry42comment</comments>
      <pubDate>Tue, 19 Mar 2024 23:31:22 +0900</pubDate>
    </item>
    <item>
      <title>[NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편</title>
      <link>https://elephant-dev.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 진행하면서, 롤링 업데이트 배포 전략을 사용하기 위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab을 통해 &lt;a href=&quot;https://www.ncloud.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;네이버 클라우드 플랫폼&lt;/a&gt; 에서 사용할 수 있는 크레딧을 제공 받아NCP에서 제공해주는 쿠버네티스를 이용해 보았다.&lt;br /&gt;진행 중에 내 입맞에 맞는 알맞는 가이드를 잘 못찾아서 해결하느라 정말 오랜 시간이 걸렸었다..!&lt;br /&gt;다음에 적용할 때는 내 포스트를 보고 빠르게 적용할 수 있도록 정리해보고자 한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 작업은 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;Platform VPC&lt;/b&gt;&lt;/span&gt;에서 작업한 내용이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;230&quot; data-origin-height=&quot;25&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m5p7v/btsFUexeEVv/VKRYxvb2evO6iU8O9mw360/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m5p7v/btsFUexeEVv/VKRYxvb2evO6iU8O9mw360/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m5p7v/btsFUexeEVv/VKRYxvb2evO6iU8O9mw360/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm5p7v%2FbtsFUexeEVv%2FVKRYxvb2evO6iU8O9mw360%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;230&quot; height=&quot;25&quot; data-origin-width=&quot;230&quot; data-origin-height=&quot;25&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;우선 구성하고자 하는 서버 구조는 이러하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;서버 구조 이미지&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;755&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d5bLrF/btsFU8JVetc/9ztDqP5Sn1z3exlkXrnw00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d5bLrF/btsFU8JVetc/9ztDqP5Sn1z3exlkXrnw00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d5bLrF/btsFU8JVetc/9ztDqP5Sn1z3exlkXrnw00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd5bLrF%2FbtsFU8JVetc%2F9ztDqP5Sn1z3exlkXrnw00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;634&quot; height=&quot;398&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;755&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;i&gt;Container Registry&lt;/i&gt; &lt;br /&gt;: 배포하고자 하는 docker image를 push할 저장소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;i&gt;Ncloud Kubernetes Service&lt;/i&gt;&lt;br /&gt;: 쿠버네티스를 편리하게 사용할 수 있도록 NCP에서 제공하는 쿠버네티스 서비스이며 노드는 2개로 구성하고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Node란 pod를 hosting 해서 사용할 수 있도록 하는 서버 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;i&gt;Kubernetes 접속 Server&lt;/i&gt;&lt;br /&gt;: master node에 직접 ssh 접속이 불가능하기 때문에 kubernetes에 접속할(kubectl을 통해 클러스터와 상호 작용 할) 서버가 한대 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;i&gt;Database Server&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 나의 경우는 또 다른 서버를 구성하여 내부에 Mysql 서버를 Master / Slave 구조로 docker image를 통해 구성해놓은게 있어서 해당 서버와 pod로 올라간 애플리케이션이 통신할 수 있어야 했다 필요 없다면 생략 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;1. Container Registry 구성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발한 애플리케이션을 배포하기 위해 우선 애플리케이션 이미지를 업로드할 저장소가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굳이 NCP에서 제공하는 Container Registry를 사용하지 않고도 docker hub를 이용하여 작업 가능하지만,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스트에서는 NCP에서 제공하는 것을 사용해서 진행해 보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Bucket 생성&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;Storage &amp;lt; Object Storage &amp;lt; Bucket Management&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9Cprc/btsFV8QmVhK/kQXTt4SQUAzotHalnpYIxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9Cprc/btsFV8QmVhK/kQXTt4SQUAzotHalnpYIxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9Cprc/btsFV8QmVhK/kQXTt4SQUAzotHalnpYIxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9Cprc%2FbtsFV8QmVhK%2FkQXTt4SQUAzotHalnpYIxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;616&quot; height=&quot;317&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;원하는 버킷 이름을 작성.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biT0Wk/btsFRbaqYze/zmcvxijkvDZIya7bn2EOAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biT0Wk/btsFRbaqYze/zmcvxijkvDZIya7bn2EOAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biT0Wk/btsFRbaqYze/zmcvxijkvDZIya7bn2EOAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiT0Wk%2FbtsFRbaqYze%2FzmcvxijkvDZIya7bn2EOAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;609&quot; height=&quot;406&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;406&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설정관리&lt;/b&gt;는 원하는 대로 하면 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBzcui/btsFUd6fa4a/uTznDSAb3VD7QodrKss331/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBzcui/btsFUd6fa4a/uTznDSAb3VD7QodrKss331/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBzcui/btsFUd6fa4a/uTznDSAb3VD7QodrKss331/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBzcui%2FbtsFUd6fa4a%2FuTznDSAb3VD7QodrKss331%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;612&quot; height=&quot;378&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;권한&lt;/b&gt;은 원하는 계정에 부여할 권한들을 체크 한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;sub Account가 있다면 추가해주시고 없다면 다음을 누르면 된다 위에 설명을 보면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소유자의 권한은 자동으로 추가되며 모든 권한이 부여된다고 되어있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 생성하기위해 로그인한 계정은 소유자 계정이므로 현재 계정으로 모든 것을 수행할 예정이라면&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다음을 눌러 넘어가도 된다!&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;전체 공개 &lt;/b&gt;의 경우 필요에 따라 선택하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;최종 확인을 한 후 &lt;b&gt;&lt;span style=&quot;background-color: #a6bc00;&quot;&gt;버킷 생성&lt;/span&gt;&lt;/b&gt; 버튼을 눌러 생성!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;218&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RcbDm/btsFUmvcijT/C8KS1EmHHUtPGRknj8PKyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RcbDm/btsFUmvcijT/C8KS1EmHHUtPGRknj8PKyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RcbDm/btsFUmvcijT/C8KS1EmHHUtPGRknj8PKyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRcbDm%2FbtsFUmvcijT%2FC8KS1EmHHUtPGRknj8PKyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;345&quot; height=&quot;218&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;218&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;생성 후 위의 내용들은 수정이 가능하니 추가 작업을 진행하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Container Registry 생성&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;Containers &amp;gt; Container Registry&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레지스트리 생성하기 버튼을 눌러 새로운 레지스트리를 추가한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCx3AG/btsFRrjRBeW/utdCktys6thlkTUfiXeCI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCx3AG/btsFRrjRBeW/utdCktys6thlkTUfiXeCI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCx3AG/btsFRrjRBeW/utdCktys6thlkTUfiXeCI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCx3AG%2FbtsFRrjRBeW%2FutdCktys6thlkTUfiXeCI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;683&quot; height=&quot;349&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 레지스트리 이름을 작성하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷은 위에서 생성한 버킷을 선택하여 생성 버튼을 누르면 완료이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AlxLT/btsFUczxPXA/qo6Ws6geG2CUPryX4UPNG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AlxLT/btsFUczxPXA/qo6Ws6geG2CUPryX4UPNG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AlxLT/btsFUczxPXA/qo6Ws6geG2CUPryX4UPNG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAlxLT%2FbtsFUczxPXA%2Fqo6Ws6geG2CUPryX4UPNG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1298&quot; height=&quot;391&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;391&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 생성 후 public Endpoint와 private Endpoint 및 login 접속 명령어가 출력 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 후 쿠버네티스에서 pod로 pull 받을 이미지 작성 시 위의 Endpoint가 필요하니 미리 복사해 두면 좋다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;2. VPC 생성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- VPC 생성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;Networking &amp;gt; VPC &amp;gt; VPC&amp;nbsp; &lt;i&gt;Management&lt;/i&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #161616; text-align: start;&quot;&gt;Naver Cloud Platform에서 VPC 환경 사용을 위해 VPC 생성하여 서브넷 구성을 해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dLRvDN/btsFTZUDxCe/3cZ6DHptNjFj7iJdbrvd11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dLRvDN/btsFTZUDxCe/3cZ6DHptNjFj7iJdbrvd11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dLRvDN/btsFTZUDxCe/3cZ6DHptNjFj7iJdbrvd11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdLRvDN%2FbtsFTZUDxCe%2F3cZ6DHptNjFj7iJdbrvd11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;691&quot; height=&quot;394&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;394&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;span style=&quot;background-color: #f0f0f0; color: #666666; text-align: center;&quot;&gt;VPC의 IP 주소 범위는, private 대역(10.0.0.0/8,172.16.0.0/12,192.168.0.0/16) 내에서 /16~/28 범위여야 합니다.&lt;/span&gt; *&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 설명에 따라 private 대역에 맞게 범위를 적용해 주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IP는 꼭 저렇게 안해도 되고 원하는 IP 대역을 private 대역 내 /16 ~ /28 범위에 맞게 설정해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;/16은 왼쪽 . 기준으로 두개를 고정하겠다는 의미&lt;/i&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Subnet 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt; &lt;i&gt;Networking &amp;gt; VPC &amp;gt; Subnet Management&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여기에서 생성할 Subnet은 총 5개 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Load balancer에 사용할 것 public, private 한개씩 - 총 2개&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;i&gt;2. &lt;/i&gt;Kubernetes 접속 Server에 사용할 것 - 1개&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. Kubernetes에 할당할 것 - 1개&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. Nat Network를 위한 것 - 1개&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;669&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt4mCw/btsFV5Gfbju/w5LnUDwesQBDHNMEQqHkJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt4mCw/btsFV5Gfbju/w5LnUDwesQBDHNMEQqHkJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt4mCw/btsFV5Gfbju/w5LnUDwesQBDHNMEQqHkJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt4mCw%2FbtsFV5Gfbju%2Fw5LnUDwesQBDHNMEQqHkJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;601&quot; height=&quot;620&quot; data-origin-width=&quot;669&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* Subnet 이름 : 자유롭게 작성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* VPC: 위에서 생성했던 VPC 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* IP 주소 범위 : VPC 범위 내에서 선택&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 가용 Zone: 서버 생성할 Zone 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* Network ACL : default 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* Internet Gateway 전용여부: kubernetes와 loadbalancer private 외 모두 public&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 용도 : LoadBlancer 용도는 LoadBlancer 선택 NatGatway는 NatGateWay선택 일반 서버는 일반 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SuGIh/btsFU0ek5Hi/WailsluKcmNPXRH43I5XmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SuGIh/btsFU0ek5Hi/WailsluKcmNPXRH43I5XmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SuGIh/btsFU0ek5Hi/WailsluKcmNPXRH43I5XmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSuGIh%2FbtsFU0ek5Hi%2FWailsluKcmNPXRH43I5XmK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;962&quot; height=&quot;214&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진과 같이 적용하면 된다 IP는 자유이지만 우선 테스트 용으로 진행한다면 동일하게 구성해도 무관하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;3. Ncloud Kubernetes Service 생성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt; &lt;i&gt;Networking &amp;gt; VPC &amp;gt; Subnet Management&lt;/i&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성하기 버튼을 눌러 생성을 시작한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 클러스터 이름을 기입하고 아래와 같이 설정해주면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;818&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coVPos/btsFWDvP3hS/l9kGeT7ixFOb31QQ140VT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coVPos/btsFWDvP3hS/l9kGeT7ixFOb31QQ140VT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coVPos/btsFWDvP3hS/l9kGeT7ixFOb31QQ140VT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoVPos%2FbtsFWDvP3hS%2Fl9kGeT7ixFOb31QQ140VT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;964&quot; height=&quot;818&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 버튼을 누르면 안내 메세지가 다음과 같이 팝업으로 뜬다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;218&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x6TC1/btsFUo7B1X9/HicG5cQ6EsZTeyNHcvoYy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x6TC1/btsFUo7B1X9/HicG5cQ6EsZTeyNHcvoYy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x6TC1/btsFUo7B1X9/HicG5cQ6EsZTeyNHcvoYy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx6TC1%2FbtsFUo7B1X9%2FHicG5cQ6EsZTeyNHcvoYy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;483&quot; height=&quot;218&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;218&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 내용은 기억해 두었다가 생성하도록 하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선은 확인 버튼을누르고 넘어가자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bColRN/btsFUpenXmL/duxgNYkpYJYD7ByfBjU2R1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bColRN/btsFUpenXmL/duxgNYkpYJYD7ByfBjU2R1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bColRN/btsFUpenXmL/duxgNYkpYJYD7ByfBjU2R1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbColRN%2FbtsFUpenXmL%2FduxgNYkpYJYD7ByfBjU2R1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;961&quot; height=&quot;616&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 서버 스펙과 노드 풀 이름을 기입하고 이 페이지 첫 장에 그렸던 서버 구조도와 같이 노드는 2개로 설정하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료 되었다면 추가 버튼을 눌러&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;237&quot; data-origin-height=&quot;291&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ca2l6m/btsFTc0Voca/VtX0uoaKnPBk0oRAhBwQHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ca2l6m/btsFTc0Voca/VtX0uoaKnPBk0oRAhBwQHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ca2l6m/btsFTc0Voca/VtX0uoaKnPBk0oRAhBwQHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fca2l6m%2FbtsFTc0Voca%2FVtX0uoaKnPBk0oRAhBwQHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;237&quot; height=&quot;291&quot; data-origin-width=&quot;237&quot; data-origin-height=&quot;291&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌측에 추가된 노드가 확인되도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFtYEr/btsFUJcIPBd/Q8Ys2De9xDya38KgnsSG81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFtYEr/btsFUJcIPBd/Q8Ys2De9xDya38KgnsSG81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFtYEr/btsFUJcIPBd/Q8Ys2De9xDya38KgnsSG81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFtYEr%2FbtsFUJcIPBd%2FQ8Ys2De9xDya38KgnsSG81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;812&quot; height=&quot;226&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;226&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가지고 있는 인증키가 있다면 보유하고 있는 인증키 이용을 하고, 없다면 새로운 키 생성을 해서 꼭 가지고 있자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;631&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqMMNb/btsFV8Xivbp/XKLMUbfGK4BBYEVtDKGpCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqMMNb/btsFV8Xivbp/XKLMUbfGK4BBYEVtDKGpCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqMMNb/btsFV8Xivbp/XKLMUbfGK4BBYEVtDKGpCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqMMNb%2FbtsFV8Xivbp%2FXKLMUbfGK4BBYEVtDKGpCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;944&quot; height=&quot;631&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;631&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음을 누르면 최종 확인이 뜨는데, 입력한 정보가 틀리지 않았는지 확인 후 &lt;span style=&quot;background-color: #a6bc00;&quot;&gt;생성하기&lt;/span&gt; 버튼을 누른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성까지는 꽤 오랜 시간이 걸린다 5~10분 정도 소요 되었던 것 같다 기다리면서 다른 작업을 진행하자!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;4. NAT Gatway 설정&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;VPC &amp;gt; NAT Gateway&amp;nbsp;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 클러스터 생성 시 팝업으로 안내가 떴던 것 처럼 Nat Gatway를 추가하도록 하겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G4jnf/btsFV834rWt/v3NTuPvfgGHhTC4JMvXmSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G4jnf/btsFV834rWt/v3NTuPvfgGHhTC4JMvXmSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G4jnf/btsFV834rWt/v3NTuPvfgGHhTC4JMvXmSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG4jnf%2FbtsFV834rWt%2Fv3NTuPvfgGHhTC4JMvXmSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;713&quot; height=&quot;460&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 생성해두었던 VPC와 NAT Gatway전용 subnet을 할당해주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유형은 공인으로 선택했고 이름은 자유롭게 기입한 후 생성 버튼을 누른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성된 NAT Gatway는 Route Table에 추가해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VPC &amp;gt; Route Table을 눌러 페이지 접속 후 해당 vpc를 선택하고 상단의 Routes 설정 버튼을 누른다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2uXh0/btsFWushPW4/KjoRJXRIbQMuxOdkYiCExK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2uXh0/btsFWushPW4/KjoRJXRIbQMuxOdkYiCExK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2uXh0/btsFWushPW4/KjoRJXRIbQMuxOdkYiCExK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2uXh0%2FbtsFWushPW4%2FKjoRJXRIbQMuxOdkYiCExK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;950&quot; height=&quot;325&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;99&quot; data-origin-height=&quot;39&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpsWBn/btsFUJDOXch/K0AeOC2RKGGO4Gthtx5gFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpsWBn/btsFUJDOXch/K0AeOC2RKGGO4Gthtx5gFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpsWBn/btsFUJDOXch/K0AeOC2RKGGO4Gthtx5gFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpsWBn%2FbtsFUJDOXch%2FK0AeOC2RKGGO4Gthtx5gFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;99&quot; height=&quot;39&quot; data-origin-width=&quot;99&quot; data-origin-height=&quot;39&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;57&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YXxJm/btsFUXBYidy/TiakizGW65vnwsMIFFyow1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YXxJm/btsFUXBYidy/TiakizGW65vnwsMIFFyow1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YXxJm/btsFUXBYidy/TiakizGW65vnwsMIFFyow1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYXxJm%2FbtsFUXBYidy%2FTiakizGW65vnwsMIFFyow1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;569&quot; height=&quot;57&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;57&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 추가해 주면 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;5. 서버 생성하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 스펙의 서버를 만들면 되는데 나의 경우 standard, CentOS 7.8 을 선택했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 서버 설정을 해주면 되는데 이전에 만들어 두었던 서버 전용 subnet과 vpc를 연결해 주면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;1164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DvaWU/btsFScmAIne/hm6TEINVQhgV8Gr2cTpq8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DvaWU/btsFScmAIne/hm6TEINVQhgV8Gr2cTpq8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DvaWU/btsFScmAIne/hm6TEINVQhgV8Gr2cTpq8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDvaWU%2FbtsFScmAIne%2Fhm6TEINVQhgV8Gr2cTpq8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;1164&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;1164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비용 절약을 위해 서버 스펙을 저렇게 설정했지만 원하는 대로 설정하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;297&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JPYK3/btsFS2D9S7r/Pm48IViEeRq8XNOKlMDlW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JPYK3/btsFS2D9S7r/Pm48IViEeRq8XNOKlMDlW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JPYK3/btsFS2D9S7r/Pm48IViEeRq8XNOKlMDlW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJPYK3%2FbtsFS2D9S7r%2FPm48IViEeRq8XNOKlMDlW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;966&quot; height=&quot;297&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;297&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 클러스터 생성 시 만들어둔 인증키를 선택해도 괜찮고 서버는 따로 인증키를 사용하고싶다면 생성 후 저장해두자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1yScm/btsFRC0cNdc/DPPjT7qJXgFmYk1zaTtjF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1yScm/btsFRC0cNdc/DPPjT7qJXgFmYk1zaTtjF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1yScm/btsFRC0cNdc/DPPjT7qJXgFmYk1zaTtjF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1yScm%2FbtsFRC0cNdc%2FDPPjT7qJXgFmYk1zaTtjF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;954&quot; height=&quot;446&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ACG는 kubernetes-vpc-default를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료가 되었다면 다음 버튼을 눌러 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 필요한 준비가 완료 되었고 2편 부터는 서버에 접속하여 kubectl을 통해 pod를 띄워보도록 하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1710859537275&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편&quot; data-og-description=&quot;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는 &quot; data-og-host=&quot;elephant-dev.tistory.com&quot; data-og-source-url=&quot;https://elephant-dev.tistory.com/42&quot; data-og-url=&quot;https://elephant-dev.tistory.com/42&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/1abnR/hyVABDWL3R/xAF9TEneMAEeggeabMe7m1/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/cBNjQH/hyVDDGTClS/nID5sJ31BFcheBMCf7hEU0/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/ZA2Yn/hyVAGkXJgb/RJeaTO15PqKdiO9opVbsA0/img.png?width=1620&amp;amp;height=682&amp;amp;face=0_0_1620_682&quot;&gt;&lt;a href=&quot;https://elephant-dev.tistory.com/42&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elephant-dev.tistory.com/42&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/1abnR/hyVABDWL3R/xAF9TEneMAEeggeabMe7m1/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/cBNjQH/hyVDDGTClS/nID5sJ31BFcheBMCf7hEU0/img.png?width=771&amp;amp;height=1049&amp;amp;face=0_0_771_1049,https://scrap.kakaocdn.net/dn/ZA2Yn/hyVAGkXJgb/RJeaTO15PqKdiO9opVbsA0/img.png?width=1620&amp;amp;height=682&amp;amp;face=0_0_1620_682');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elephant-dev.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud Platform/Naver Cloud</category>
      <category>naver cloud</category>
      <category>Ncloud Kubernetes Service</category>
      <category>ncp</category>
      <category>NCP kubernetes</category>
      <category>ncp kubernetes service</category>
      <category>네이버클라우드 쿠버네티스</category>
      <category>쿠버네티스</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/41</guid>
      <comments>https://elephant-dev.tistory.com/41#entry41comment</comments>
      <pubDate>Tue, 19 Mar 2024 15:38:03 +0900</pubDate>
    </item>
    <item>
      <title>[F-Lab] F-Lab 멘토링 Java Backend 과정 3개월 차 후기</title>
      <link>https://elephant-dev.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;지난 2023년 11월 F-Lab 멘토링을 시작하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현 시점 3개월 차에 접어들었고, F-Lab 멘토링 기간을 회고하고자 후기를 작성해보려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab을 신청하기 전 정말 많은 후기를 찾아봤던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결코 작지 않은 금액을 지불해야 하는 시스템이었고, 이미 4년의 시간을 현 직장에서 허비한 시간이 많다고 느껴 조급한 마음을 가진 나에겐 너무나도 간절했으며 그렇기에 더 신중하게 고민하게 되었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;멘토링을 시작하기 까지&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 무언가를 배우기로 마음먹었다면 적어도 나의 문제가 무엇인지를 파악하는 것이 중요하다고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 정리되었던 나의 문제는 이러했다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;내가 가지고 있는 문제는 무엇인가.&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;이직하고자 하는 곳의 기술스택을 현 직장에서 경험할 수 없다.&lt;/li&gt;
&lt;li&gt;현 직장에서 사용되고 있는 기술 스택은 다른 회사에서 필요로 하는 곳이 많이 없다.&lt;/li&gt;
&lt;li&gt;이직을 하기 위해 새로운 기술스택을 사용하고자 프로젝트를 시작하면 어디서부터 어디까지 어느 정도로 구현해야 하는지 몰라 끝까지 진행하지 못하고 있다.&lt;/li&gt;
&lt;li&gt;이직하기 위해서 어느 정도의 지식과 어느정도의 역량을 필요로 하는지 모르고 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 마디로 정리하자면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;내 경력이 물경력이라 느끼고 있으며 이직하기 위해 무엇을 어떻게 어느만큼 준비해야하는지 모르고 있다는 것&lt;/span&gt;&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 많이 답답했고, 많이 힘들었고 그럼에도 이 질문들에 속시원히 답변을 들을 수 있는 지인 개발자가 없어 막막했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도,&amp;nbsp; 또 한 때는 편한 현실에 안주하고 있는 내 자신과 타협을 하기도 했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 2년 전에 Java라는 언어로 전향하고자 퇴사하고 새로 배우고자 마음먹었었고 그때 당시 F-Lab의 가격이 너무 비싸&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감당할 수 없었고 다른 플랫폼의 학습 코스로 공부를 시작해보고자 하였으나,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 Java를 시켜준다는 퇴사 만류에 기대를 가지고 지금까지 재직 중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 불편한 현실은 그 이후 한 번도 Java를 다룰 기회가 주어지지 않았으며 그렇게 2년이라는 시간이 흘러버렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 고민에 빠진 나는 F-Lab을 마주하게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6개월 과정에서 4개월로 바뀌고, 가격도 이전보다는 저렴해져 있었으며 이런저런 이유로 2년을 허비한 나에게 돈보다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 더 중요했었고 2년 전의 나보다 지금의 나는 훨씬 더 간절해져 있었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;F-Lab에 합류하기까지 고민했던 내용은 다음과 같다.&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;회사와 병행할 수 있는가?&lt;/li&gt;
&lt;li&gt;온라인으로 진행되는가?&lt;/li&gt;
&lt;li&gt;내가 정말 잘 성장할 수 있는가?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 후기를 보게 될 사람들은 이미 많은 F-Lab 후기를 거쳐 이곳으로 왔겠지만 반복되는 말은 언제나 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&quot;깊이 있는 학습&quot;이라는&lt;/span&gt;&lt;/b&gt; 말이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깊이 있는 학습이라는 말이 얼마나 무서운 말인지 그런 학습을 제대로 경험하지 못했었던 그때는 알지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 깊이 있는 학습을 해본 사람이나, F-Lab을 진행하고 있는, 또는 수료한 사람들은 알 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깊이 있는 학습이 얼마나 나 자신이 모르는 게 많은 사람인지 민낯을 보게 되는 과정이라는 것을.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 개발하는 것이 정말 많이 행복하고, 개발자라는 직업이 너무 좋다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 시작할 때에도 지금도 변함없이 개발을 사랑하는 나는 개발을 잘 해내기에 지식이 많이 부족한 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제대로 된 개발자가 되고 맘껏 개발을 즐기기 위해 또 성공적인 언어 전향을 위해 F-Lab을 진행하기로 마음먹었고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java Backed 즉시시작 코스로 결제하게 되었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;멘토링의 시작&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멘토링 전까지 F-Lab 페이지에 정말 많이 들어가 봤던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멘토링을 하기 위한 팁이나, 어떤 자세로 임해야 하는지, 어떤 학습을 해야하는지, 시작 전까지 추천 책 등 정말 많은 가이드가 존재하고 있어 많은 도움이 되었었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 결제를 마치고 멘토링 시작까지 기다리고 있다면 한번 홈페이지를 샅샅히 찾아보길 바란다!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;F-Lab 홈페이지&quot; href=&quot;https://f-lab.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://f-lab.kr/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1707184100865&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;F-Lab - 상위 1% 개발자들의 멘토링&quot; data-og-description=&quot;아마존, 페이스북, MS, 네카라쿠배 등 상위 1% IT기업 출신 개발자들이 초급 개발자를 중급 개발자로 레벨업 시켜주는 멘토링 서비스&quot; data-og-host=&quot;f-lab.kr&quot; data-og-source-url=&quot;https://f-lab.kr/&quot; data-og-url=&quot;https://f-lab.kr&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/EnEsu/hyVf7CCsz1/XiOtd1n95myHdEj3A0jiP1/img.jpg?width=934&amp;amp;height=521&amp;amp;face=0_0_934_521&quot;&gt;&lt;a href=&quot;https://f-lab.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://f-lab.kr/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/EnEsu/hyVf7CCsz1/XiOtd1n95myHdEj3A0jiP1/img.jpg?width=934&amp;amp;height=521&amp;amp;face=0_0_934_521');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;F-Lab - 상위 1% 개발자들의 멘토링&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;아마존, 페이스북, MS, 네카라쿠배 등 상위 1% IT기업 출신 개발자들이 초급 개발자를 중급 개발자로 레벨업 시켜주는 멘토링 서비스&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;f-lab.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멘토링 날짜가 다가오기 전까지 추천해 주신 책을 읽으며 정말 설레고 떨리는 첫 멘토링을 기다렸던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab의 학습 방식은 멘토님이 질문하시고 내가 그에 맞게 답변하는 식으로 이뤄진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(여러분이 만나게 될 멘토분들은 정말 똑똑하신 분들이다. 평소처럼 얕게 학습했다가는 아무 질문에도 대답 하지 못할 것이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 멘토링 시간은 언제나 절망의 반복이었던 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문을 하시고 내 대답에 대한 꼬리질문을 반복해 주시는데, 알고는 있으나 설명하지 못하는 것들도 많았고 분명 학습했지만 꼬리질문에 말문이 막혔던 적이 대부분이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab은 정말 자신과의 싸움이다. 재직 중에 멘토링을 진행한다면 정말 각오를 남다르게 해야 할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점심시간엔 삼각김밥을 먹으며 멘토님이 추가 과제로 제안해 주신 학습을 수행하려 했으며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사가 끝나면 집 가서 밥을 먹고 바로 공부를 시작했고, 주말에는 인생 처음 스터디카페라는 곳을 가서 수험생 때처럼 공부를 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 아무리 내 모든 시간을 다 할애해도 시간은 너무 부족하고 빠르게 지나가는 시간들은 너무 야속하게 느껴지며 그런 시간을 보내고도 나는 모든 질문에 완벽히 대답하지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 자신이 답답하고 많은 좌절을 하게 되기도 했고 한편으로는 억울하기도 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나 정말 열심히 한 것 같은데 왜 아무것도 공부 안 한 사람처럼 대답을 하지 못하지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 이 굴레에 빠지며 우울함과 동시에 꼭 나랑 싸워 이긴다는 마인드로 이 악물었던 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 F-Lab에서 공부하지 않았더라면 지나쳤을 만한 것들도 다 세세히 공부했고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나 스스로 꼬리질문 하는 법을 배우며 더 깊이 있게 학습하고자 하게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멘토님을 만나기 전 F-Lab에서 제공하는 꼬리질문 시스템도 활용해서 다시 재 점검하는 시간도 가지며 꼬리질문 이번주 1등을 해보기도 했었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F8dCf/btsEnWZWpZm/eAcKKQq6yaczHM8ve1kXB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F8dCf/btsEnWZWpZm/eAcKKQq6yaczHM8ve1kXB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F8dCf/btsEnWZWpZm/eAcKKQq6yaczHM8ve1kXB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF8dCf%2FbtsEnWZWpZm%2FeAcKKQq6yaczHM8ve1kXB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;170&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;262&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 결과 간혹 한 회차의 멘토링에서는 답을 잘하는 날도 있게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 생각해도 그때 정말 행복했었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item tenping&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;SMALL&lt;/div&gt;
    &lt;tenping class=&quot;adsbytenping&quot; style=&quot;width: 100%; max-width: 768px; margin: 0 auto; display: block;&quot; mediaid=&quot;5167770&quot; tenping-ad-display-type=&quot;UD8Mia8gyIoT5Z2MT6VB3Q%3d%3d&quot;&gt;&lt;/tenping&gt;
    &lt;script src=&quot;//tads.tenping.kr/scripts/adsbytenping.min.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 배정받았던 멘토님은 내가 인생을 살면서 만나본 사람들 중 가장 열정이 넘치는 분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 든든하다고 매번 느끼고 지금도 그 생각이 변함없다. 어떻게 나를 위해 저렇게 까지 노력해 주시지?라고 느낄 정도로 최고의 멘토를 만났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 모든 질문에 빠른 답을 해주셨고, 나의 고민에 공감하고 이해해 주셨고 더 나아가서는 나보다 나를 위하는 사람 혹은 나만큼이나 내가 원하는 바를 이루기를 바라주시는 분이시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 은인 같은 분을 만났고 그 덕에 멘토님을 실망시켜 드리고 싶지 않다는 생각이 내 열정과 더해져 더 열심히 하고자 했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금도 여전히 멘토링 과정을 진행 중에 있고, 프로젝트를 시작하며 어떻게 좋은 회사에서는 코드를 리뷰하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 고민을 하는지 배워나가고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 나는 프로젝트를 어디까지 구현하고 테스트해야 하는지 몰라 백엔드 포지션을 원함에도 불구하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백을 구현하고 테스트하기 위해 프론트까지 구현해나가며 프론트 지옥에 빠져나오질 못하고 그렇게 어영부영 손을 놓게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 백엔드 포지션에서는 어떻게 테스트를 하고, 어떤 고민을 하고 어떤 생각을 하며 개발해야 하는지 멘토님께서 내 잘못된 생각들을 많이 바로 잡아 주시고 계시다..(감사합니다..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 물경력인 내 경력을 살려서 어떻게 프로젝트를 구성할 수 있을지 조언도 많이 해주셨다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 어디서 이런 귀인을 또 만날 수 있을지 모른다...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 하면서 멘토님한테 정말 이런 것도 모른다고? 싶은 내용도 많이 여쭤봤던 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 창피하긴 하다 부끄럽고 이런 것도 모르는 나는 내가 봐도 좀 아니지 않나 싶을 때도 많다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 나는 배우는 사람이니까 부끄럽다고 아는 척해봐야 어차피 다 들통나고 더 큰 부끄럼을 당하는 것보다 낫다고 생각한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab의 멘토 체제는 다른 교육 프로그램과는 다른 것이 내 질문들에 대해 멘토님이 정답을 무조건적으로 말씀해주시지 않는다. 다만 제대로 학습할 기회를 만들어 주실 뿐이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;857&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5c2ge/btsEm9SRowC/xeGx6xGRN3gFJBS6klnT4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5c2ge/btsEm9SRowC/xeGx6xGRN3gFJBS6klnT4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5c2ge/btsEm9SRowC/xeGx6xGRN3gFJBS6klnT4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5c2ge%2FbtsEm9SRowC%2FxeGx6xGRN3gFJBS6klnT4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;353&quot; height=&quot;498&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;857&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 질문에 대해 내가 어느 것을 모르고 있는지 파악하게 도와주시고 역질문을 통해 내가 알아낼 수 있도록 도와주시기도 하신다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 진행해 나가고 있는 지금 많이 설레고 좋다..! 또 얼마나 성장하게 될지 내가 너무 기대되기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 연말부터 시작해 연초까지 이어 학습하고 있는 나는 연말보다 상대적으로 바쁜 연초인 지금 이전보다 더 시간을 할애하고 있지 못하다고 느낀다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 허겁지겁 지식을 쌓기 바빴던 나는 배웠던 것을 많이 기억하지 못하고 있는 것 같다고 멘토님께서 피드백을 해주시기도 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이전의 내 모습을 회고하며 다시 더 열정적인 나로 돌아가고 지나온 시간을 다시 복기하며 단단하게 성장하고자 후기를 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 후기를 보고 F-Lab을 고민하는 사람에게 이런 말을 전하고 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab을 하며 나는 내 성장이 정말 많이 기대되는 날들로 가득 차게 되었고, 내가 생각했던 것보다 더 좋은 멘토를 만나 많이 든든한 마음을 가지게 되었다고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 네카라쿠배를 가고 싶다는 마음을 가지기보다는 제대로 된 학습을 하고자 하는 마음으로 바뀌게 되었다고.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab 시작하고 자신의 인생에서 다시 돌아봐도 열심히 했다 혹은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 돌아간대도 그때만큼 공부할 수 없을 것 같다고 느낄 정도로 열정을 가지고 임한다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 기업을 들어가게 되는 것보다 더 가치 있는 것을 얻게 될 거라고 나는 확신을 가지고 전할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 자세로 모든 과정을 수료했다면 좋은 기업은 핵심 가치가 아닌 부가 가치가 되어있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adfit&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;728x90&lt;/div&gt;
    &lt;ins class=&quot;kakao_ad_area&quot; style=&quot;display: none;&quot; data-ad-unit=&quot;DAN-Hoq7taZ4INVtpDZ9&quot; data-ad-width=&quot;728px&quot; data-ad-height=&quot;90px&quot;&gt;&lt;/ins&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;//t1.daumcdn.net/kas/static/ba.min.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남은 기간을 아쉽지 않은 한 순간순간들로 채우기를 나 자신에게 당부하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F-Lab에서 학습한 순간들을 잘 활용하여 좋은 성과를 낸 F-Lab 수료 후기를 기약하며 후기를 마친다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분의 개발인생과 나의 개발인생 모두 화이팅!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;007&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/007.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/007.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(F-Lab 친구 추천 원하시는 분 들은 &lt;a href=&quot;https://open.kakao.com/o/snz4vgNg&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://open.kakao.com/o/snz4vgNg&lt;/a&gt; 오픈채팅으로 연락 주세요!)&lt;/p&gt;</description>
      <category>회고</category>
      <category>f-lab</category>
      <category>F-Lab 후기</category>
      <category>flab</category>
      <category>flab 3개월 후기</category>
      <category>flab후기</category>
      <category>Java backed 과정</category>
      <category>에프랩</category>
      <category>에프랩 3개월 후기</category>
      <category>에프랩멘토링</category>
      <category>자바백엔드과정</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/40</guid>
      <comments>https://elephant-dev.tistory.com/40#entry40comment</comments>
      <pubDate>Tue, 6 Feb 2024 10:52:06 +0900</pubDate>
    </item>
    <item>
      <title>[PostgreSQL] Extension function in C (c 소스코드로 db 함수 생성)</title>
      <link>https://elephant-dev.tistory.com/39</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오라클에 이어 이번엔 PostgreSQL에서 C소스로 함수 생성 해 보았다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;오라클과 비교해 보자면 오라클은 리스너 설정하는 부분이 제일 까다로웠으며, C소스코드 내부에서는 평소 작성하던&lt;br /&gt;C문법 그대로 사용하면 되어 DB로 리턴하는 법을 알아내는 것에 시간을 많이 소요했었지만,&lt;br /&gt;PostgreSQL 같은 경우에는 PG에서 제공하는 API를 사용하여 PostgreSQL이 제공하는 데이터 타입을 찾아 소스코드를 짜야 하는 점이 어려웠던 점이었다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이전 포스팅에서는 오라클의 경우, C내부 함수의 작성이나 데이터 타입 등 평소에 쓰던 문법과 다르지 않아 크게 C소스코드 작성법에 대해 설명하지 않았는데 PostgreSQL의 경우 C소스코드를 잘 작성해야 함수 생성과 호출이 문제없이 잘 이루어 지므로 C소스코드 작성법의 설명을 덧붙였다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PostgreSQL Extension function을 사용 하는 방법은 다음과 같다.&lt;/b&gt;&lt;br /&gt;1. 사용하고 싶은 코드를 pg에서 제공하는 데이터형식을 이용하여 C언어로 작성한다.&lt;br /&gt;2. C언어를 .so라이브러리로 빌드한다.&lt;br /&gt;3. PG에 접속하여 2번에서 만든 라이브러리 경로를 주어 db에 &lt;span style=&quot;color: #555555;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;함수를 &lt;/span&gt;생성한다.&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;i&gt;&lt;b&gt;1. 사용하고 싶은 코드를 pg에서 제공하는 데이터형식을 이용하여 C언어로 작성한다.&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 PostgreSQL에서 제공하는 데이터 타입은 아래와 같다.&amp;nbsp;&lt;br /&gt;나의 경우, 문자열을 받아 받은 문자열을 가공하여, 가공한 문자열을 리턴하는 형식의 함수를 만들고자 했다.&lt;br /&gt;필요한 return타입은 C에선 char*이지만, 아래 표에서 나타난대로 SQL Type에 varchar형식으로 출력하려면 VarChar*라는 데이터 타입을 사용해야 했고, 이 타입은 postgres.h파일에 정의되어있다고 표기되어있으므로 참고하여 소스코드를 작성하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;1418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QH3bf/btr3CmE3sH2/Rj6BVdhUkNR5Gja9PKY3UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QH3bf/btr3CmE3sH2/Rj6BVdhUkNR5Gja9PKY3UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QH3bf/btr3CmE3sH2/Rj6BVdhUkNR5Gja9PKY3UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQH3bf%2Fbtr3CmE3sH2%2FRj6BVdhUkNR5Gja9PKY3UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;656&quot; height=&quot;1129&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;1418&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;우선 작성한 소스코드를 통해 설명을 이어가보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &quot;server/postgres.h&quot;
#include &quot;server/fmgr.h&quot;
#include &quot;utils/builtins.h&quot; // $PG_HOME/include 위치에 존재하는 파일이므로, header파일의 위치에 맞게 조정해야함

PG_MODULE_MAGIC; //PG 매크로 

PG_FUNCTION_INFO_V1(f_test_elephant); // PG에서 호출할 fucntion이름
Datum f_test_elephant(PG_FUNCTION_ARGS)
{
&amp;nbsp;&amp;nbsp;	VarChar* input_dat = (VarChar *)PG_GETARG_VARCHAR_P(0);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int i = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char *input_str = NULL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char input_temp[1024+1] = {0,};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char output_str[1024+1] = {0,};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;input_dat = (char *)VARDATA(input_dat);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;strncpy(input_temp, input_str, strlen(input_str)+1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(i = 0; i &amp;lt; 1024; i++)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	if( input_temp[i] == 0x00 )
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	input_temp[i] = 'A';
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		input_temp[i] += input_temp[i];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

	memcpy(output_str, input_temp, strlen(input_temp)+1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;

&amp;nbsp;&amp;nbsp; PG_RETURN_VARCHAR_P(cstring_to_text(output_str));&amp;nbsp;&amp;nbsp;// varchar 타입으로 return 하는 함수 (내부의 cstring_to_text()함수는 PG에서 지정한 구조체에 데이터를 담는 함수).
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선적으로 include 헤더파일들은 내가 사용하고자 하는 함수가 선언된 헤더파일만 포함하면되는데 위의 코드에서 사용된 함수들은 위 3가지 헤더파일에 선언되어있다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;파일을 작성하기 전 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;PG_MODULE_MAGIC;&lt;/b&gt;&lt;/span&gt; 이 매크로를 사용하는 것은 필수이다.&amp;nbsp;&lt;br /&gt;이 매크로의 내용은 &lt;span style=&quot;color: #333333;&quot;&gt;fmgr.h에&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&lt;/span&gt;아래의 사진처럼 선언되어있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5CIjf/btr3iIW5xW6/bh1AgwE15KlZ3qhtClfDT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5CIjf/btr3iIW5xW6/bh1AgwE15KlZ3qhtClfDT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5CIjf/btr3iIW5xW6/bh1AgwE15KlZ3qhtClfDT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5CIjf%2Fbtr3iIW5xW6%2Fbh1AgwE15KlZ3qhtClfDT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;711&quot; height=&quot;184&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 매크로는 dlsym으로서의 기능을 사용하기 위해 필요하며, &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;백엔드에서 데이터가 아닌 기능에서만 작동하도록 보장된다고 한다&lt;/span&gt;&lt;/span&gt;. 이 매크로가 없으면 에러가 발생하니 실행 할 함수를 작성하기 앞서 반드시 포함해야한다.&lt;br /&gt;&lt;br /&gt;실행하고자 하는 함수의 이름을 이 매크로 안에 넣어 실행 할 C함수 위에 다음 매크로를 사용해야한다&lt;b&gt;&lt;/b&gt;&lt;b&gt;.&lt;/b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;PG_FUNCTION_INFO_V1(f_test_elephant); &lt;/b&gt;&lt;/span&gt;이 매크로는 fmgr.h에 아래와 같이 선언되어있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;781&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xrMqC/btr3GSjChNw/RrCqcK4VNSlW2atuTokfE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xrMqC/btr3GSjChNw/RrCqcK4VNSlW2atuTokfE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xrMqC/btr3GSjChNw/RrCqcK4VNSlW2atuTokfE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxrMqC%2Fbtr3GSjChNw%2FRrCqcK4VNSlW2atuTokfE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;781&quot; height=&quot;235&quot; data-origin-width=&quot;781&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지정된 함수 이름과 연결된 정보 함수를 작성하는 매크로이다. PG에서 자동으로 &lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PGDLEXPORT를 할 수 있도록 하고, 함수이름에 대한 외부 선언을 제공할 수 있도록 하는 매크로이다. C로 작성된 소스코드를 db 함수로 선언하여 사용할 것이기때문에 필요한 부분이다.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;보면은 extern Datum funcname (PG_FUNCTION_ARGS)라고 작성되어있는데 우리는 그 형식에 맞게 함수를 써주면 된다. 때문에 C함수를 &lt;i&gt;&lt;b&gt;Datum&amp;nbsp;f_test_elephant(PG_FUNCTION_ARGS)&lt;/b&gt;&lt;/i&gt;로 동일한 형태로 맞추어 작성해주었다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;Datum&lt;/b&gt;&lt;/span&gt;&amp;nbsp; 은 postgres.h에 보면 Datum 타입은 내가 사용 할 VarChar 타입을 포함한 거의 모든 타입으로 변환이 가능한 것으로 확인할 수 있으며, 내부에서 사용한 char *형식을 Datum 형식으로 변환할 수 있는 함수를 제공하고있기 때문에 데이터 return에 용이했다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;인자값으로 들어온 데이터는 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;VarChar* input_dat = (VarChar *)PG_GETARG_VARCHAR_P(0);&amp;nbsp;&lt;/b&gt;&lt;/span&gt;를 통해 함수 내부 변수로 받을 수 있으며, 그 값은 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;input_dat&amp;nbsp;=&amp;nbsp;(char&amp;nbsp;*)VARDATA(input_dat);&lt;/b&gt;&lt;/span&gt; 이 매크로를 통해 C 내부에서 우리가 잘 알고있는 데이터타입 형태로 변경하여 사용할 수 있다.&lt;br /&gt;여기에서 주의 할 점은 VarChar의 선언부를 쫓아가다보면 구조체 형태인 것을 다음과 같이 확인할 수 있는데, 데이터를 직접 건드리지 말라고 쓰여있으므로 반드시 내부의 데이터를 건들일 때에는 PG에서 제공하는 매크로를 이용하여 값을 변경하거나 쓰도록 해야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/liWnw/btr3eAel8OO/d9juJQlYHSdySTe8xiGQo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/liWnw/btr3eAel8OO/d9juJQlYHSdySTe8xiGQo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/liWnw/btr3eAel8OO/d9juJQlYHSdySTe8xiGQo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FliWnw%2Fbtr3eAel8OO%2Fd9juJQlYHSdySTe8xiGQo1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;582&quot; height=&quot;322&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 db함수에서 넘겨준 파라미터를 C에서 사용할 수 있는 char*형태로 변환했으니 하고싶은 가공을 하고, 가공이 완료 된 데이터를 return할 차례만 남아있다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;PG에서 접근 할 C소스코드의 return형은 Datum 형태로 되어있으니 우리 역시 Datum 형태로 변환을 해 주어야 한다.&lt;br /&gt;Datum 형태로 변환하는 것은 builtins.h에 함수로 정의되어있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;40&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LzMCW/btr3oeuxIX6/uBQtxKuEpZ4C23vbicGRWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LzMCW/btr3oeuxIX6/uBQtxKuEpZ4C23vbicGRWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LzMCW/btr3oeuxIX6/uBQtxKuEpZ4C23vbicGRWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLzMCW%2Fbtr3oeuxIX6%2FuBQtxKuEpZ4C23vbicGRWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;448&quot; height=&quot;40&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;char*형태를 text로 변환해주고, text라는 데이터타입도 역시 varlena 구조체이므로, VarChar 형태로 변환하는 것과 동일하다.(c.h에서 확인 가능)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;305&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rh0PE/btr3fsUHZ3Q/ktRfaencz3qUwn5u7XNnl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rh0PE/btr3fsUHZ3Q/ktRfaencz3qUwn5u7XNnl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rh0PE/btr3fsUHZ3Q/ktRfaencz3qUwn5u7XNnl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frh0PE%2Fbtr3fsUHZ3Q%2FktRfaencz3qUwn5u7XNnl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;305&quot; height=&quot;102&quot; data-origin-width=&quot;305&quot; data-origin-height=&quot;102&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 변환 된 데이터를 PG_RETURN_VARCHAR_P 메크로를 이용하여 varchar 타입으로 return 해 주면 된다.&amp;nbsp;&lt;br /&gt;헤더파일을 보면은 다양한 변수형태를 제공하고 있으니 VarChar 타입이 아닌 다른 타입으로 return이 필요하신 분들도 참고하여 만들면 금방 습득이 가능 할 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2hNfy/btr3dEnRXAY/1hwdaZq0CCyipOIjf4jrJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2hNfy/btr3dEnRXAY/1hwdaZq0CCyipOIjf4jrJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2hNfy/btr3dEnRXAY/1hwdaZq0CCyipOIjf4jrJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2hNfy%2Fbtr3dEnRXAY%2F1hwdaZq0CCyipOIjf4jrJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;551&quot; height=&quot;298&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;298&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 과정에서 캐스팅을 잘못하면 다음과 같은 에러가 발생하니 잘 확인해야한다.&lt;br /&gt;server&amp;nbsp;closed&amp;nbsp;the&amp;nbsp;connection&amp;nbsp;unexpectedly &lt;br /&gt;This&amp;nbsp;probably&amp;nbsp;means&amp;nbsp;the&amp;nbsp;server&amp;nbsp;terminated&amp;nbsp;abnormally &lt;br /&gt;before&amp;nbsp;or&amp;nbsp;while&amp;nbsp;processing&amp;nbsp;the&amp;nbsp;request. &lt;br /&gt;The&amp;nbsp;connection&amp;nbsp;to&amp;nbsp;the&amp;nbsp;server&amp;nbsp;was&amp;nbsp;lost.&amp;nbsp;Attempting&amp;nbsp;reset:&amp;nbsp;Failed.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;i&gt;&lt;b&gt;2. C언어를 .so라이브러리로 빌드한다.&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 1에서 열심히 작성한 코드를 라이브러리로 빌드하면 되는데, 우리는 소스코드를 작성할 때 Postgresql에서 제공하는 헤더파일이 굉장히 많이 필요했으므로, 헤더파일을 같은 위치에 옮겨서 빌드하던가, 그게 아니라면 빌드 옵션으로 헤더파일의 위치를 링크하여 빌드해주어야 빌드가 오류없이 완료된다.&lt;br /&gt;나의 경우 메이크파일을 만들었지만, 메이크파일에는 환경적인 요소를 포함하여 만들기만 하면 되므로 혼란을 주지 않기 위해 헤더파일과 같은 위치에서 빌드 했을 경우의 예시를 들었다.&amp;nbsp;&lt;br /&gt;메이크 파일으로 빌드 할 사람들은 라이브러리 빌드에 필요한 아래의 옵션을 메이크파일에 넣어 빌드하면 된다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;cc -fPIC -c test_elephant.c
cc -shared -o test_elephant.so test_elephant.o&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;i&gt;&lt;b&gt;3. PG에 접속하여 2번에서 만든 라이브러리 경로를 주어 db에&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;i&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;i&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;i&gt;&lt;b&gt;함수를&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;i&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;i&gt;&lt;b&gt;생성한다.&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;sql&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;-- 함수 생성부
REATE OR REPLACE FUNCTION f_test_elephant(varchar) RETURNS varchar
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AS '/home/elephant/pgsql/include/server/test_elephant.so', 'f_test_elephant'
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LANGUAGE C STRICT;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
--함수 실행부
select f_test_elephant('test string');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;오라클 보다는 C함수 작성이 어렵지만, 또 db내부에서 해야할 설정들은 비교적 간단하고 쉽다.&lt;br /&gt;생각보다 어렵지 않으니 필요한 상황에 유용하게 사용하기를 바란다!&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;참고&amp;gt;&lt;br /&gt;&lt;a href=&quot;https://postgresql.kr/docs/13/sql-createfunction.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;https://postgresql.kr/docs/13/sql-createfunction.html&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;CREATE FUNCTION&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;CREATE FUNCTION CREATE FUNCTION &amp;mdash; 새 함수 정의 요약 CREATE [ OR REPLACE ] FUNCTION 이름 ( [ [ 인자모드 ] [ 인자이름 ] 인자자료형 [ { DEFAULT | = } 기본값표현식 ] [, ...] ] ) [ RETURNS 반환자료형 | RETURNS TABLE ( 칼럼&quot; data-og-host=&quot;postgresql.kr&quot; data-og-source-url=&quot;https://postgresql.kr/docs/13/sql-createfunction.html&quot; data-og-url=&quot;https://postgresql.kr/docs/13/sql-createfunction.html&quot;&gt;&lt;a href=&quot;https://postgresql.kr/docs/13/sql-createfunction.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://postgresql.kr/docs/13/sql-createfunction.html&quot;&gt;
&lt;div class=&quot;og-image&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CREATE FUNCTION&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;CREATE FUNCTION CREATE FUNCTION &amp;mdash; 새 함수 정의 요약 CREATE [ OR REPLACE ] FUNCTION 이름 ( [ [ 인자모드 ] [ 인자이름 ] 인자자료형 [ { DEFAULT | = } 기본값표현식 ] [, ...] ] ) [ RETURNS 반환자료형 | RETURNS TABLE ( 칼럼&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;postgresql.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/xfunc-c.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #f3f5f9;&quot;&gt;https://www.postgresql.org/docs/current/xfunc-c.html&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;38.10.&amp;nbsp;C-Language Functions&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;38.10.&amp;nbsp;C-Language Functions 38.10.1. Dynamic Loading 38.10.2. Base Types in C-Language Functions 38.10.3. Version 1 Calling Conventions 38.10.4. Writing Code 38.10.5. &amp;hellip;&quot; data-og-host=&quot;www.postgresql.org&quot; data-og-source-url=&quot;https://www.postgresql.org/docs/current/xfunc-c.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ckoxLd/hyRU5Au8TD/aKUBKaLlERF1LyNCmEowqK/img.png?width=540&amp;amp;height=557&amp;amp;face=0_0_540_557&quot; data-og-url=&quot;https://www.postgresql.org/docs/15/xfunc-c.html&quot;&gt;&lt;a href=&quot;https://www.postgresql.org/docs/15/xfunc-c.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.postgresql.org/docs/current/xfunc-c.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ckoxLd/hyRU5Au8TD/aKUBKaLlERF1LyNCmEowqK/img.png?width=540&amp;amp;height=557&amp;amp;face=0_0_540_557');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;38.10.&amp;nbsp;C-Language Functions&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;38.10.&amp;nbsp;C-Language Functions 38.10.1. Dynamic Loading 38.10.2. Base Types in C-Language Functions 38.10.3. Version 1 Calling Conventions 38.10.4. Writing Code 38.10.5. &amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.postgresql.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Database/PostgreSQL</category>
      <category>pg c-language function</category>
      <category>pg C언어 함수</category>
      <category>PG extension function</category>
      <category>pg function in c</category>
      <category>Postgres 동적함수</category>
      <category>postgreSQL function in c</category>
      <category>The connection to the server was lost. Attempting reset: Failed.</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/39</guid>
      <comments>https://elephant-dev.tistory.com/39#entry39comment</comments>
      <pubDate>Mon, 13 Mar 2023 13:55:58 +0900</pubDate>
    </item>
    <item>
      <title>[Oracle] Oracle External Procedure 사용하기 ( in C )</title>
      <link>https://elephant-dev.tistory.com/38</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle External Procedure를 통해 함수를 만들고 실행해야 할 일이 있어,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링을 엄청나게 하고 많은 에러가 나기를 반복한 후 결국 성공해냈다..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링을 하면서 내가 원하는 정보를 찾기 너무 어려웠어서 나중에 또 이렇게 사용해야 할 일이 있을 경우와&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나처럼 Oracle External Procedure를 사용해야 할 일이 있는 사람들을 위해 정리를 해 본다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle External Procedure는 C언어로 작성 된 코드를 라이브러리화 하여, Oracle 내부에 함수 또는 프로시저로&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선언하여 C언어 코드를 호출할 수 있는 기능이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Oracle External Procedure를 사용 하는 방법은 다음과 같다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사용하고 싶은 코드를 C언어로 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. C언어를 .so라이브러리로 빌드한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 오라클 리스너에 External procedure를 사용할 수 있도록 설정해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 오라클에 접속하여 2번에서 만든 라이브러리 경로를 주어 db에 라이브러리를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 4에서 생성한 라이브러리를 통해 호출 함수 또는 프로시저를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 경우, 문자열을 받아 그 문자열을 내부코드에서 변형하여 변형 된 문자열을 return하고자 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우에서의 예시코드와 함께 External procedure를 생성해 보자!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;i&gt;&lt;b&gt;1. 사용하고 싶은 코드를 C언어로 작성한다.&lt;/b&gt;&lt;/i&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1678435290105&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include&amp;lt;stdio.h&amp;gt;
#include&amp;lt;string.h&amp;gt;

char *test_elephant(char *input_str, char *output_str)
{
	char input_temp[1024+1] = {0,};
    int i = 0;
    
    strncpy(input_temp, input_str, strlen(input_str)+1);
    
    for(i = 0; i &amp;lt; 1024; i++)
    {
    	if( input_temp[i] == 0x00 )
        	input_temp[i] = 'A';
        else
    		input_temp[i] += input_temp[i];
    }

	memcpy(output_str, input_temp, strlen(input_temp)+1);
    
    return (char *)output_str;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 엄청엄청 간단한 코드를 작성해보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 짠 이유는 procedure로 input_str에 varchar 값을 넣어서 호출한 후, output_str에 담아 return하고 싶어서인데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 가장 중요한 점은!! ( 꼭 유념해야함) &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;함수 호출 시 리턴받을 버퍼 output_str을 받아와야 한다는 점&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 생각을 해보자면 위 소스코드에서 왜 굳이 output_str을 받아서 return을 하지..? 라고 생각할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 위 코드에서 보면은 input_str에서 들어온 문자열의 길이보다 return될 문자열의 길이가 훨씬 길 수도 있다는 것을 생각할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 점에서 내가 여러가지 시도한 방법으로는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 지역변수에 선언한 데이터에 문자열을 담아 return 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; =&amp;gt; 오라클 함수로 출력 시 값이 안나와서 실패.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. input_str에 담아서 return 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; =&amp;gt; 한번은 출력되고 한번은 ORA-28575: unable to open RPC connection to external procedure agent 에러가 출력되며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;문제 발생 ( 이 경우 C 내부 함수에서 문제가 있을 경우 발생하거나 네트워크가 제대로 연결되지 않을 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;발생한다고 하는데, 아마도 들어온 버퍼보다 나가는 버퍼 사이즈가 커서 오버플로우가 나지 않았을까..하는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;생각이다. 왜냐하면 들어온데이터가 크고, 나간 데이터가 작을 때는 정상적으로 잘 수행했기 때문..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 여러번의 삽질 후 정상적으로 잘 출력 하기 위한 소스코드가 바로 위의 예시이다 왜 저렇게 작성했는지는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 프로시저를 보면 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;i&gt;&lt;b&gt;2. C코드를 .so 라이브러리로 빌드한다.&lt;/b&gt;&lt;/i&gt;&lt;i&gt;&lt;b&gt;&lt;/b&gt;&lt;/i&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1678436048020&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;--linux
gcc -fPIC -m64 -nostdlib -c test_elephant.c -o test_elephant.o
gcc -fPIC -m64 -nostdlib -shared test_elephant.o -o test_elephant.so

--HP-UX
cc +DD64 -DSS_64BIT_SERVER -c   test_elephant.c
cc +DD64 -DSS_64BIT_SERVER -b -o test_elephant.sl test_elephant.o&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 커맨드로 C코드를 라이브러리로 빌드해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 &lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;라이브러리는 반드시 Oracle이 접근할 수 있는 경로에 두어야 한다&lt;/span&gt;&lt;/b&gt;..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지 않으면 라이브러리를 읽을 권한이 없다는 에러가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;i&gt;&lt;b&gt;3. 오라클 리스너에 External procedure를 사용할 수 있도록 설정해준다.&lt;/b&gt;&lt;/i&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ORACLE_HOME/network/admin/&lt;b&gt;listener.ora &lt;/b&gt;파일에 External procedure를 사용할 수 있도록 셋팅을 해줘야하는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빨간색 부분이 추가 해 줘야할 부분이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA1912&amp;nbsp;= &lt;br /&gt;&amp;nbsp;&amp;nbsp;(DESCRIPTION_LIST&amp;nbsp;= &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(DESCRIPTION&amp;nbsp;= &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT =1523)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt; &amp;nbsp;(ADDRESS&amp;nbsp;=&amp;nbsp;(PROTOCOL&amp;nbsp;=&amp;nbsp;IPC)(KEY&amp;nbsp;=&amp;nbsp;EXTPROC1523))&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) &lt;br /&gt;&amp;nbsp;&amp;nbsp;) &lt;br /&gt;&lt;br /&gt;SID_LIST_ora1912&amp;nbsp;= &lt;br /&gt;&amp;nbsp;(SID_LIST&amp;nbsp;= &lt;br /&gt;&amp;nbsp;&amp;nbsp;(SID_DESC&amp;nbsp;= &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;(ORACLE_HOME = /oracle/ora1912/ORA19/product/19.3.0.0/db_1) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;(SID_NAME&amp;nbsp;=&amp;nbsp;ora1912) &lt;br /&gt;&amp;nbsp;&amp;nbsp;) &lt;br /&gt;&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;(SID_DESC&amp;nbsp;= &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(SID_NAME&amp;nbsp;=&amp;nbsp;PLSExtProc) &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(ORACLE_HOME = /oracle/ora1912/ORA19/product/19.3.0.0/db_1) &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(PROGRAM=extproc) &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(ENVS=&quot;EXTPROC_DLLS=ANY&quot;))&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;&amp;nbsp;)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윗 부분에 있는 KEY 작성부는 EXTPROC+PORT번호로 적어주는게 편리하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하단에 ENVS=~ 여기는 나는 ANY로 설정해두었지만 특정 라이브러리에만 접근하게 하려면 그 라이브러리의 경로를 적어주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ORACLE_HOME/network/admin/&lt;b&gt;tnsnames.ora&lt;/b&gt; 파일에도 External procedure를 사용할 수 있도록 셋팅을 해줘야한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;EXTPROC_CONNECTION_DATA&amp;nbsp;=&amp;nbsp; &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;nbsp;(DESCRIPTION&amp;nbsp;= &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1523)) &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(CONNECT_DATA&amp;nbsp;=&amp;nbsp;(SID&amp;nbsp;=&amp;nbsp;PLSExtProc) &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;)&lt;/b&gt;&lt;/span&gt; &lt;br /&gt;ora1912&amp;nbsp;= &lt;br /&gt;&amp;nbsp;&amp;nbsp;(DESCRIPTION&amp;nbsp;= &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1523)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(CONNECT_DATA&amp;nbsp;= &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(SERVER&amp;nbsp;=&amp;nbsp;DEDICATED) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(SERVICE_NAME&amp;nbsp;=&amp;nbsp;ORA1912) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) &lt;br /&gt;&amp;nbsp;&amp;nbsp;)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서 주의 할 점은 KEY는 반드시 listener.ora에 작성했던 키와 동일한 키로 작성해줘야한다**&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 리스너 설정이 모두 완료되었으면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lsnrctl stop / lsnrctl start 명령어로 리스너를 재 기동 시켜서 인식시켜줘야한다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p04nE/btr3bYEZ9WO/QFBbKSkkQ0P8x3b4ZayoCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p04nE/btr3bYEZ9WO/QFBbKSkkQ0P8x3b4ZayoCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p04nE/btr3bYEZ9WO/QFBbKSkkQ0P8x3b4ZayoCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp04nE%2Fbtr3bYEZ9WO%2FQFBbKSkkQ0P8x3b4ZayoCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;838&quot; height=&quot;184&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로PLSExtProc가 뜬 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;*리스너 설정에 External Procedure 설정을 제대로 하지 않으면 에러가 발생하니 External Procedure 생성 시 관련 에러가 떨어지면 반드시 리스너 설정을 제대로 했는 지 설정 후 재기동 했는지 꼭 확인해야한다.*&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;i&gt;&lt;b&gt;4. 오라클에 접속하여 2번에서 만든 라이브러리 경로를 주어 db에 라이브러리를 생성한다.&lt;/b&gt;&lt;/i&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 sqlplus로 sysdba 접속 후 library 생성 권한을 줘야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1678437005159&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;grant CREATE LIBRARY to [유저이름];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 function 또는 procedure를 생성 할 유저로 접속 후 라이브러리를 생성해 준다&lt;/p&gt;
&lt;pre id=&quot;code_1678437144563&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;create or replace library [라이브러리이름] as '라이브러리가 위치한 경로';/
ex)create or replace library elephantlib as '/oracle/ora1912/ORA19/product/19.3.0.0/db_1/test_elephant.so';/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주의 할 점은 라이브러리 위치가 oracle 계정이 접근 불가능한 위치에 라이브러리가 있으면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 function 또는 procedure를 생성하고 실행할 때 라이브러리 접근이 불가능하다는 에러가 발생하므로 위치를 잘 지정해서 라이브러리를 옮겨놓아야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;i&gt;&lt;b&gt;5. 4에서 생성한 라이브러리를 통해 호출 함수 또는 프로시저를 만든다.&lt;/b&gt;&lt;/i&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 경우 프로시저를 만들고, 프로시저를 function으로 호출하도록 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 return할 데이터가 있고, 그 데이터의 타입이 varchar2형인데 return시 담아 줄 버퍼의 크기가 담으려는 데이터보다 사이즈가 작으면 ORA-28575: unable to open RPC connection to external procedure agent 에러가 발생한다고 위에서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말한 바가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 나의 수많은 테스트로는 애초에 실행을 할 때 버퍼 사이즈의 크기를 지정하여 받아와야 에러가 발생하지 않아서 이렇게 생성해 주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1678666173070&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;--procedure 생성
create or replace procedure
p_test_elephant(input IN VARCHAR2, output OUT VARCHAR2) 
as external
language C
library elephantlib
name &quot;test_elephant&quot; 
parameters(input   string, output string);

--procedure 호출 function 생성
create or replace function f_test_elephant(input varchar2)
return varchar2
is
   output varchar2(1024);
BEGIN
   p_test_elephant(input,output); 
   DBMS_OUTPUT.PUT_LINE(output);
   return output;
end;
/

--함수 실행부
select f_test_elephant('test text') from dual;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 처음부터 function으로 생성하고 실행하고 싶다면 다음과 같은 방법으로도 사용 가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1678666422804&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;--function 생성
create or replace function
f_test_elephantinput IN VARCHAR2, output OUT VARCHAR2) return varchar2
as external
language C
library elephantlib
name &quot;test_elephant&quot;
parameters(input   string, output string);
/

--함수 실행부
DECLARE
   input varchar2(1024);
   output varchar2(1024);
   result varchar2(1024);
BEGIN
   input := '집어넣을 문자열';
   result := f_test_elephant(input,output); 
   DBMS_OUTPUT.PUT_LINE(output);
end;
/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 줄의 SQL로 깔끔하게 실행하기 위해서는 위의 방법이 더 괜찮은 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열을 return하기 위한 예제가 없어 어려움이 많았지만 다른 int나 float형의 return 방식으로는 오라클이 제공하는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메뉴얼을 참고하면 쉽게 구현 가능하니 다른 return형으로 작성을 원하는 사람은 아래 링크의 오라클 문서를 참고하면 도움이 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/cd/A58617_01/server.804/a58236/10_procs.htm#426081&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.oracle.com/cd/A58617_01/server.804/a58236/10_procs.htm#426081&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1678671002172&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;External Procedures&quot; data-og-description=&quot;Note: To call a packaged function from SQL statements, you must use the pragma RESTRICT_REFERENCES, which asserts the purity level of the function (the extent to which the function is free of side effects). PL/SQL cannot check the purity level of the corre&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/cd/A58617_01/server.804/a58236/10_procs.htm#426081&quot; data-og-url=&quot;https://docs.oracle.com/cd/A58617_01/server.804/a58236/10_procs.htm#426081&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/cd/A58617_01/server.804/a58236/10_procs.htm#426081&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/cd/A58617_01/server.804/a58236/10_procs.htm#426081&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;External Procedures&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Note: To call a packaged function from SQL statements, you must use the pragma RESTRICT_REFERENCES, which asserts the purity level of the function (the extent to which the function is free of side effects). PL/SQL cannot check the purity level of the corre&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Database/Oracle</category>
      <category>external procedure</category>
      <category>external procedure example</category>
      <category>external procedure in c</category>
      <category>ORA-28575</category>
      <category>oracle external procedure</category>
      <category>oracle external procedure c example</category>
      <category>oracle external procedure example in C</category>
      <category>오라클 C 라이브러리</category>
      <category>오라클 C 함수</category>
      <category>오라클 외부 프로시저</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/38</guid>
      <comments>https://elephant-dev.tistory.com/38#entry38comment</comments>
      <pubDate>Mon, 13 Mar 2023 09:22:59 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 코딩테스트 연습 - 숫자 짝궁(C)</title>
      <link>https://elephant-dev.tistory.com/37</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-링크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131128&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/131128&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670674947836&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131128&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/43YYN/hyQQvg9mAj/owqjTLmrmVB4gv2GQ79ILk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cE6inx/hyQQreIzk5/Tk1mUwxSi8PUbt58ECChTk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131128&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131128&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/43YYN/hyQQvg9mAj/owqjTLmrmVB4gv2GQ79ILk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cE6inx/hyQQreIzk5/Tk1mUwxSi8PUbt58ECChTk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-문제 설명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;두 정수&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;X,&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Y의 임의의 자리에서 공통으로 나타나는 정수 k(0 &amp;le; k &amp;le; 9)들을 이용하여 만들 수 있는 가장 큰 정수를 두 수의 짝꿍이라 합니다(단, 공통으로 나타나는 정수 중 서로 짝지을 수 있는 숫자만 사용합니다).&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;X,&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Y의 짝꿍이 존재하지 않으면, 짝꿍은 -1입니다.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;X,&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Y의 짝꿍이 0으로만 구성되어 있다면, 짝꿍은 0입니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어,&lt;span&gt;&amp;nbsp;&lt;/span&gt;X&lt;span&gt;&amp;nbsp;&lt;/span&gt;= 3403이고&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y&lt;span&gt;&amp;nbsp;&lt;/span&gt;= 13203이라면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;X와&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 짝꿍은&lt;span&gt;&amp;nbsp;&lt;/span&gt;X와&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y에서 공통으로 나타나는 3, 0, 3으로 만들 수 있는 가장 큰 정수인 330입니다. 다른 예시로&lt;span&gt;&amp;nbsp;&lt;/span&gt;X&lt;span&gt;&amp;nbsp;&lt;/span&gt;= 5525이고&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y&lt;span&gt;&amp;nbsp;&lt;/span&gt;= 1255이면&lt;span&gt;&amp;nbsp;&lt;/span&gt;X와&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 짝꿍은&lt;span&gt;&amp;nbsp;&lt;/span&gt;X와&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y에서 공통으로 나타나는 2, 5, 5로 만들 수 있는 가장 큰 정수인 552입니다(X에는 5가 3개,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y에는 5가 2개 나타나므로 남는 5 한 개는 짝 지을 수 없습니다.)&lt;br /&gt;두 정수&lt;span&gt;&amp;nbsp;&lt;/span&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y가 주어졌을 때,&lt;span&gt;&amp;nbsp;&lt;/span&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 짝꿍을 return하는 solution 함수를 완성해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-제한사항&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3 &amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 길이(자릿수) &amp;le; 3,000,000입니다.&lt;/li&gt;
&lt;li&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y는 0으로 시작하지 않습니다.&lt;/li&gt;
&lt;li&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 짝꿍은 상당히 큰 정수일 수 있으므로, 문자열로 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-입출력 예&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&quot;100&quot;&lt;/td&gt;
&lt;td&gt;&quot;2345&quot;&lt;/td&gt;
&lt;td&gt;&quot;-1&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&quot;100&quot;&lt;/td&gt;
&lt;td&gt;&quot;203045&quot;&lt;/td&gt;
&lt;td&gt;&quot;0&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&quot;100&quot;&lt;/td&gt;
&lt;td&gt;&quot;123450&quot;&lt;/td&gt;
&lt;td&gt;&quot;10&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&quot;12321&quot;&lt;/td&gt;
&lt;td&gt;&quot;42531&quot;&lt;/td&gt;
&lt;td&gt;&quot;321&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&quot;5525&quot;&lt;/td&gt;
&lt;td&gt;&quot;1255&quot;&lt;/td&gt;
&lt;td&gt;&quot;552&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-입출력 예 설명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 #1&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 짝꿍은 존재하지 않습니다. 따라서 &quot;-1&quot;을 return합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 #2&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 공통된 숫자는 0으로만 구성되어 있기 때문에, 두 수의 짝꿍은 정수 0입니다. 따라서 &quot;0&quot;을 return합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 #3&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 짝꿍은 10이므로, &quot;10&quot;을 return합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 #4&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;X,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Y의 짝꿍은 321입니다. 따라서 &quot;321&quot;을 return합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 #5&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지문에 설명된 예시와 같습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-해설&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 숫자를 역순으로 정렬하여 처음부터 차근차근 겹치는 숫자 순서대로 출력하면 끝나는 간단한 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 들어온 두 X,Y 배열을 큰 숫자 -&amp;gt; 작은 숫자 순서대로 정렬한 후 for문을 돌려 일치하는 숫자를 answer에 담아줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교 대상 배열을 두고 다른 배열을 for문으로 돌려가면서 탐색할 때 같은 문자를 발견했을 시 break를 태우고 멈춥니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 탐색할 수를 가지고있다가. 비교 대상 배열을 다음으로 찾을 때 마지막으로 탐색했 던 위치 다음 부터 탐색하는 것이 탐색할 때 시간을 줄일 수 있습니다. 만일 맨 첫 번째로 찾은 값이 0이라면 그 다음 탐색은 필요없습니다. 0이 한개든 00으로 두개 던 숫자로 표현하면 0과 같기 때문에 그 부분도 예외처리를 하여 탐색 시간을 줄여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 찾은 값이 아무것도 없다면 -1을 넣고 정답을 도출하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-풀이(C)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1670675048901&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;

int sort(const void* a, const void* b){
    return (*(char*)b - *(char*)a); 
}

char* solution(const char* X, const char* Y) {
    char* answer = (char *)malloc(3000000+1);
    int x_len = strlen(X);
    int y_len = strlen(Y);
    char* x_cpy = (char *)malloc(x_len+1);
    char* y_cpy = (char *)malloc(y_len+1);
    int pos = 0;
    int ans_pos = 0;
  
    memset(x_cpy, 0x00, x_len+1);
    memset(y_cpy, 0x00, y_len+1);
    strcpy(x_cpy, X);
    strcpy(y_cpy, Y);
      
    qsort(x_cpy, x_len, sizeof(char), sort);
    qsort(y_cpy, y_len, sizeof(char), sort);
    
    for(int i = 0; i &amp;lt; x_len; i++){
        for(int j = pos; j &amp;lt; y_len; j++){
            if(x_cpy[i] == y_cpy[j]){
                answer[ans_pos++] = x_cpy[i];
                pos = j+1;
                break;
            }
        }
        if(pos == y_len || answer[0] == '0') break;
    }
    
    if(pos == 0) strcpy(answer ,&quot;-1&quot;);

    return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm/Programmers</category>
      <category>c 숫자짝꿍</category>
      <category>숫자짝꿍 프로그래머스</category>
      <author>코끼리 개발자</author>
      <guid isPermaLink="true">https://elephant-dev.tistory.com/37</guid>
      <comments>https://elephant-dev.tistory.com/37#entry37comment</comments>
      <pubDate>Sat, 10 Dec 2022 22:32:31 +0900</pubDate>
    </item>
  </channel>
</rss>