<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>LaMelD</title><link>https://lameld.github.io/</link><description>Recent content on LaMelD</description><generator>Hugo</generator><language>ko-KR</language><lastBuildDate>Mon, 14 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://lameld.github.io/index.xml" rel="self" type="application/rss+xml"/><item><title>알고리즘 풀이 저장소 정리</title><link>https://lameld.github.io/algorithms/overview/</link><pubDate>Mon, 14 Sep 2026 00:00:00 +0000</pubDate><guid>https://lameld.github.io/algorithms/overview/</guid><description>&lt;p&gt;흩어져 있던 풀이 저장소(Cpp-Solution, Python-Solution, programmers)를 &lt;a href="https://github.com/LaMelD/algorithms"&gt;algorithms&lt;/a&gt; 하나로 합쳤다. 커밋 이력은 그대로 남겼고, 구조만 언어별로 정리했다.&lt;/p&gt;</description></item><item><title>RP-CHAT: 캐릭터와 1:1로 대화하는 RP 챗봇</title><link>https://lameld.github.io/projects/rp-chat/</link><pubDate>Fri, 29 May 2026 00:00:00 +0000</pubDate><guid>https://lameld.github.io/projects/rp-chat/</guid><description>&lt;p&gt;저장소: &lt;a href="https://github.com/LaMelD/RP-CHAT"&gt;github.com/LaMelD/RP-CHAT&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;미리 정의된 캐릭터와 1:1로 대화하는 학습용 챗봇이다. 응답은 소설 대본처럼 &lt;strong&gt;지문(이탤릭) + 대사(굵게, 큰따옴표)&lt;/strong&gt; 형식으로 스트리밍된다. 처음에는 도구 호출을 하는 ReAct 어시스턴트로 시작했다가, 캐릭터 일관성을 우선하기로 하고 캐릭터 RP 전용으로 방향을 바꿨다.&lt;/p&gt;</description></item><item><title>메모리 스토리지 엔진</title><link>https://lameld.github.io/mariadb/engine-memory/</link><pubDate>Sun, 09 Apr 2023 00:00:00 +0000</pubDate><guid>https://lameld.github.io/mariadb/engine-memory/</guid><description>&lt;h2 id="특징"&gt;특징&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;메모리 스토리지 엔진을 사용하는 테이블의 데이터는 디스크를 사용하지 않고 메모리 내에만 저장되고 엑세스 된다.&lt;/p&gt;</description></item><item><title>1장 쉘 스크립트 개요</title><link>https://lameld.github.io/shell/ch01/</link><pubDate>Wed, 15 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/shell/ch01/</guid><description>&lt;h3 id="11-unixlinux-소개-및-특징"&gt;1.1 UNIX/Linux 소개 및 특징&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;1.1.1 UNIX&#10;&lt;ul&gt;&#10;&lt;li&gt;1969년 AT&amp;amp;T 벨연구소의 직원이 켄 톰슨, 데니스 리치, 더글라스 매클로리 등이 최초로 개발하였으며, 이후 C언어로 재작성되어 다양한 플랫폼에 이식될 수 있도록 보완되었다.&lt;/li&gt;&#10;&lt;li&gt;벨연구소는 대학과 연구기관에 UNIX를 활용할 수 있도록 라이선스를 제공하였으며, 버클리 대학교에서는 UNIX에 네트워크 프로토콜인 TCP/IP 등 다양한 기능을 보강하여 BSD 배포본을 제작하고 이후 파생되는 많은 UNIX에 영향을 끼쳤다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;1.1.2 Linux&#10;&lt;ul&gt;&#10;&lt;li&gt;1991년 리누스 토발즈라는 핀란드 헬싱키 대학의 대학원생에 의해 커널이 개발된 이래, 1984년부터 리처드 스토람에 의해 추진된 GNU 프로젝트의 다양한 소프트웨어들이 합쳐진 운영체제가 Linux이다.&lt;/li&gt;&#10;&lt;li&gt;개인용 데스크톱 환경뿐만 아니라 안드로이드 등 스마트폼에서부터 기업용 엔터프라이즈 환경에 이르기까지 다양한 플랫폼에 이식되어 활용중이다.&lt;/li&gt;&#10;&lt;li&gt;대표적인 리눅스 배포판에는 데비안, 레드햇, 슬렉웨어, SUSE, 우분투, 젠투가 있으며 그밖에도 다양한 배포본들이 파생되어 개발되고 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="12-쉘의-역할-및-특징"&gt;1.2 쉘의 역할 및 특징&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;쉘은 운영체제에서 커널(Kernel)과 사용자 사이의 인터페이스, 즉 가교 역할을 하는 프로그램으로, 운영체제의 내부 명령어나 응용프로그램을 실행하는 것을 지원한다.&lt;/li&gt;&#10;&lt;li&gt;시스템을 전체적으로 보면 운영체제는 결국 하드웨어의 한 부분인 저장장치의 일부에 저장된다.&lt;/li&gt;&#10;&lt;li&gt;운영체제를 좀 더 세부적으로 살펴보면, 운영체제가 설치되어 있는 저장장치(DISK 등)를 비롯하여 모니터, 그래픽카드, NIC 등 시스템에 직간접적으로 연결되는 하드웨어를 통제하는 커널과 이러한 커널과 사용자 및 응용 프로그램 사이에서의 명령을 전달을 담당하는 쉘로 구분할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;운영체제 마다 기본적으로 다양한 쉘을 제공하고 있고 사용자가 별도의 쉘을 설치해서 활용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;CDE(Common Desktop Environment)&#10;&lt;ul&gt;&#10;&lt;li&gt;공통 데스크톱 환경(CDE)은 유닉스를 위한 그래픽 데스크톱 환경이며 모티프 위젯 툴킷을 도입하고 있다.&lt;/li&gt;&#10;&lt;li&gt;유닉스 표준화 단체들 가운데 하나인 공통 개방형 소프트웨어 환경이 지정한 유닉스 GUI 규격이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="13-쉘의-종류"&gt;1.3 쉘의 종류&lt;/h3&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;구분&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;개발자&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;설치 위치&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;설명&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;sh&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Stephen Bouren&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;/bin/sh&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;대부분의 UNIX 및 Linux에 설치되어 있는 쉘&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;bash&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Brain Fox, Chet Ramey&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;/bin/bash&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Linux의 기본 쉘로 sh와 호환&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ksh&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;David Korn&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;/bin/ksh&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;1980년대 벨연구서에서 개발, 부동 소수점 계산이 가능&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;csh&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Bill Joy&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;/bin/csh&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;C언어와 비슷한 스타일로 Script를 작성 가능&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;tcsh&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Ken Greer&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;/bin/tcsh&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;csh에 커맨드 히스토리 등 추가 기능을 보완&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;쉘 종류의 확인&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ps -p $$&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;/etc/passwd 파일의 내용 중 마지막 필드에 기술된 쉘 경로를 보고 확인할 수 있다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user01:x:500:500::/home/user01:/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;시스템에 항상 자신이 원하는 쉘이 설치되어 있을 거라고 생각하면 안된다.&lt;/li&gt;&#10;&lt;li&gt;대부분의 UNIX/Linux 시스템에 기본적으로 설치되어 있는 sh를 중심으로 설명할 것이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="14-쉘-스크립트란"&gt;1.4 쉘 스크립트란?&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴퓨터 사용의 편의성을 확보한 GUI 기반의 실행 환경인 Windows 초기 버전이 있었지만 DOS를 통해 구동되는 DOS의 확장 프로그램 수준이었기 때문에 일반 사용자가 쉽게 사용하기에는 어려움이 있었다.&lt;/li&gt;&#10;&lt;li&gt;이러한 번거로움을 조금이나마 해소하고자 DOS 구성 시 메모리 구성 및 드라이버 로딩을 케이스별로 메뉴로 구성하여 케이스별로 선택할 수 있는 배치 파일을 만들어 활용하는 사람들이 있었다.&lt;/li&gt;&#10;&lt;li&gt;그 당시의 배치 파일을 지금의 쉘 스크립트와 비슷한 개념으로 이해하면 된다.&lt;/li&gt;&#10;&lt;li&gt;쉘 스크립트 : 운영체제의 쉘에서 사용할 수 있는 명령어를 해석하고 그 결과를 커널에게 전달하는 프로그램&lt;/li&gt;&#10;&lt;li&gt;쉘 : 사용자가 내린 명령어를 해석하고 그 결과를 커널에게 전달하는 프로그램&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="15-쉘-스크립트-활용-시-이점"&gt;1.5 쉘 스크립트 활용 시 이점&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;1.5.1 반복 작업에 대한 자동화 기능&#10;&lt;ul&gt;&#10;&lt;li&gt;쉘 스크립트를 활용하는 가장 큰 장점은 관리자의 번거로움을 덜 수 있다.&lt;/li&gt;&#10;&lt;li&gt;스케줄 설정과 같이 주기적으로 수행하는 단순한 작업에 단순한 작업에 쉘 스크립트를 활용하면 관리자가 일일이 타이핑하지 않아도 된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;1.5.2 기존의 명령어를 사용자만의 명령어로 보완&#10;&lt;ul&gt;&#10;&lt;li&gt;기본적으로 UNIX/Linux는 POSIX라는 표준 규약을 준수하지만 모든 명령어가 통일된 것은 아니기 때문에 운영체제 마다 명령 옵션이나 결과 형식에 약간의 차이가 있다.&lt;/li&gt;&#10;&lt;li&gt;운영체제에서 제공하는 명령어 실행 결과를 사용자가 원하는 형식으로 재구성해야 할 때가 있다.&lt;/li&gt;&#10;&lt;li&gt;예시&#10;&lt;ul&gt;&#10;&lt;li&gt;운영체제가 다른 시스템에서 동일한 형태의 로그를 추출해야 할 때가 있다.&lt;/li&gt;&#10;&lt;li&gt;이 경우, 쉘 스크립트를 이용하여 기존의 명령어의 결과를 원하는 형태의 결과로 표시할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;이를 위해 입출력 재지정(Rdirection)을 활용하면 된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;1.5.3 손쉽고 빠른 개발 및 보완이 가능&#10;&lt;ul&gt;&#10;&lt;li&gt;기본적으로, 쉘 스크립트 자체는 운영체제의 명령어 등을 묶어서 프로그램화한 후 인터프리터 방식으로 수행되기 때문에 별도의 컴파일러를 설치할 필요가 없다.&lt;/li&gt;&#10;&lt;li&gt;운영체제의 명령어들을 잘 알고 있다면 손쉽고 빠른 개발 및 보완이 가능하다.&lt;/li&gt;&#10;&lt;li&gt;필요한 절차를 기술하는 것이다.&lt;/li&gt;&#10;&lt;li&gt;시스템 관리자가 관리하는 여러 대의 서버 및 원격지에 있는 서버를 설정하거나 패치할 때 쉘 스크립트를 활용하면 설정 및 패치 작업을 보다 더 효율적으로 할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;POSIX(Portable Operating System Interface)&#10;&lt;ul&gt;&#10;&lt;li&gt;서로 다른 UNIX OS의 공통 API를 정리하여 이식성이 높은 유닉스 응용 프로그램을 개발하기 위한 목적으로 IEEE가 책정한 어플리케이션 인터페이스 규격이다.&lt;/li&gt;&#10;&lt;li&gt;대부분의 시스템들이 AT&amp;amp;T에서 개발된 UNIX에 뿌리를 두고 있지만 시간이 흐르면서 다양한 제조사와 개발자의 손을 거치면서 운영체제별 의존성 문제가 발생되었다.&lt;/li&gt;&#10;&lt;li&gt;POSIX는 운영체제별 의존성 문제를 해결하기 위해 서로 다른 UNIX 운영체제에서 공통 API를 정리하여 운영체제간 이식성이 높은 UNIX 응용 프로그램을 개발하기 위한 목적으로 제정된 API 규격이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>1-1 : AWS란?</title><link>https://lameld.github.io/aws/ch01-1/</link><pubDate>Mon, 13 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/aws/ch01-1/</guid><description>&lt;h3 id="aws란"&gt;AWS란?&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Amazon Web Service는 Amazon에서 제공하는 클라우드 서비스이다.&lt;/li&gt;&#10;&lt;li&gt;네트워크 기반으로 가상 컴퓨터와 스토리지를 비롯한 다양한 서비스를 제공하고 있다.&lt;/li&gt;&#10;&lt;li&gt;2004년 Amazon Simple Queue Service(SQS)부터 시작되었다.&lt;/li&gt;&#10;&lt;li&gt;2006년 온라인 스토리지 서비스(S3)와 가상 컴퓨터 서비스(EC2)부터 AWS가 본격적으로 시작되었다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="클라우드란"&gt;클라우드란?&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;클라우드 컴퓨팅 : 컴퓨터 리소스의 이용 형태&lt;/li&gt;&#10;&lt;li&gt;클라우드는 컴퓨터의 계산 리소스, 스토리지 영역, 어플리케이션 처리를 네트워크 기반 서비스로 제공한다.&lt;/li&gt;&#10;&lt;li&gt;인프라스트럭처 서비스(Infrastructure as a Service : IaaS)&#10;&lt;ul&gt;&#10;&lt;li&gt;가상 서버 또는 스토리지 등의 리소스를 인터넷을 기반으로 제공하는 서비스를 의미한다.&lt;/li&gt;&#10;&lt;li&gt;사용자는 물리적인 하드웨어를 관리할 필요가 없으며, 직접적으로 컴퓨터 리소스를 사용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;가장 아래의 기초적이 부분을 담당한다.&lt;/li&gt;&#10;&lt;li&gt;물리 장치에 가장 가까운 서비스라고 할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;플랫폼 서비스(Platform as a Service : PaaS)&#10;&lt;ul&gt;&#10;&lt;li&gt;데이터베이스 또는 어플리케이션 서버 등의 미들웨어를 제공하는 서비스&lt;/li&gt;&#10;&lt;li&gt;OS와 미들웨어의 관리는 제공자가 한다.&lt;/li&gt;&#10;&lt;li&gt;사용자는 미들웨어만을 직접 사용할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;어플리케이션 서비스(Software as a Service : SaaS)&#10;&lt;ul&gt;&#10;&lt;li&gt;소프트웨어 또는 어플리케이션의 기능을 인터넷을 통해 제공한다.&lt;/li&gt;&#10;&lt;li&gt;SaaS를 제공하는 것을 SaaS 제공자(Provider)라고 한다. 이는 ASP(Application Service Provider)와 거의 같은 것이다.&lt;/li&gt;&#10;&lt;li&gt;ASP라는 형태의 서비스 제공은 클라우드 이전부터 있었지만 SaaS 제공자는 클라우드라는 것에 조금 더 비중을 두어 말하는 것이라고 생각하면 된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="물리-서버on-premise와-aws의-차이"&gt;물리 서버(On Premise)와 AWS의 차이&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;물리 서버 : 조직 내부에서 사용할 목적으로 준비한 설비&lt;/p&gt;</description></item><item><title>CH01. 도커의 기본</title><link>https://lameld.github.io/docker/ch-01/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-01/</guid><description>&lt;h2 id="1-도커란-무엇인가"&gt;1. 도커란 무엇인가?&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;도커&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너형 가상화 기술을 구현하기 위해 상주 어플리케이션과 이 어플리케이션을 조작하기 위한 명령행 도구로 구성되는 프로덕트다.&lt;/li&gt;&#10;&lt;li&gt;어플리케이션 배포에 특화되어 있기 때문에 어플리케이션 개발 및 운영을 컨테이너 중심으로 할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;도커의 역사&lt;/p&gt;</description></item><item><title>md2html: 마크다운을 저장하면 HTML이 따라 생기는 Claude Code 플러그인</title><link>https://lameld.github.io/projects/md2html/</link><pubDate>Tue, 26 May 2026 00:00:00 +0000</pubDate><guid>https://lameld.github.io/projects/md2html/</guid><description>&lt;p&gt;저장소: &lt;a href="https://github.com/LaMelD/md2html"&gt;github.com/LaMelD/md2html&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;.md&lt;/code&gt; 파일을 작성하거나 수정할 때마다 같은 디렉토리에 &lt;code&gt;.html&lt;/code&gt;이 자동으로 생기는 Claude Code 플러그인이다. 산출물은 두 개다.&lt;/p&gt;</description></item><item><title>시퀀스 스토리지 엔진</title><link>https://lameld.github.io/mariadb/engine-sequence/</link><pubDate>Sun, 09 Apr 2023 00:00:00 +0000</pubDate><guid>https://lameld.github.io/mariadb/engine-sequence/</guid><description>&lt;h2 id="특징"&gt;특징&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;단순히 순차적인 번호를 주어진 조건에 맞게 생성만 해주는 스토리지 엔진&lt;/p&gt;</description></item><item><title>2장 실습 환경 구축</title><link>https://lameld.github.io/shell/ch02/</link><pubDate>Mon, 03 Aug 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/shell/ch02/</guid><description>&lt;h3 id="21-unixlinux-시스템-구축"&gt;2.1 UNIX/Linux 시스템 구축&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;2.1.1 가상머신 설치&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;x86에 설치되지 않는 UNIX/Linux 버전은 사용이 불가능하다.(IMB의 AIX, HP의 HP-UX, SUN의 SPARC CPU 버전 Solaris 등)&lt;/li&gt;&#10;&lt;li&gt;VMware 또는 VirtualBox 설치&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;2.1.2 게스트 운영체제 설치&lt;/p&gt;</description></item><item><title>1-2 : AWS의 네트워크 서비스</title><link>https://lameld.github.io/aws/ch01-2/</link><pubDate>Mon, 13 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/aws/ch01-2/</guid><description>&lt;p&gt;&lt;strong&gt;네트워크는 AWS의 서비스를 지탱하는 가장 중요한 인프라라고 할 수 있다.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>CH02. 도커 컨테이너 배포</title><link>https://lameld.github.io/docker/ch-02/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-02/</guid><description>&lt;h2 id="1-컨테이너로-어플리케이션-실행하기"&gt;1. 컨테이너로 어플리케이션 실행하기&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;도커 이미지 : 도커 컨테이너를 구성하는 파일 시스템과 실행할 어플리케이션 설정을 하나로 합친 것으로 컨테이너를 생성하는 템플릿 역할을 한다.&lt;/p&gt;</description></item><item><title>백준 풀이 목록</title><link>https://lameld.github.io/algorithms/baekjoon/</link><pubDate>Sun, 29 Mar 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/algorithms/baekjoon/</guid><description>&lt;p&gt;&lt;a href="https://github.com/LaMelD/algorithms/tree/master/cpp/Beakjoon"&gt;algorithms/cpp/Beakjoon&lt;/a&gt;에 있는 백준 C++ 풀이 112문제의 목록이다. 번호를 누르면 백준 문제 페이지로, &lt;code&gt;코드&lt;/code&gt;를 누르면 풀이 파일로 간다.&lt;/p&gt;</description></item><item><title>Network</title><link>https://lameld.github.io/cloudbasic/network/</link><pubDate>Tue, 31 Dec 2019 13:23:21 +0900</pubDate><guid>https://lameld.github.io/cloudbasic/network/</guid><description>&lt;h3 id="191230-monday--200103-friday"&gt;191230 Monday ~ 200103 Friday&lt;/h3&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-기본적으로-알아야-할-컴퓨터-기초"&gt;1. 기본적으로 알아야 할 컴퓨터 기초&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;데이터 표현&#10;&lt;ul&gt;&#10;&lt;li&gt;2진법, 10진법, 16진법(0x00)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;HW 구성요소&#10;&lt;ul&gt;&#10;&lt;li&gt;CPU(central processing unit)&#10;&lt;ul&gt;&#10;&lt;li&gt;processor : 물리적 코어&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;RAM(memory : random access memory) : 주 기억&#10;&lt;ul&gt;&#10;&lt;li&gt;process : 실행되고 있는 프로그램&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;하드 디스크(SSD/HDD) : 보조 기억&lt;/li&gt;&#10;&lt;li&gt;I/O 장치&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;운영 체제(OS : operating system)&#10;&lt;ul&gt;&#10;&lt;li&gt;하드웨어를 관리해주는 프로그램&lt;/li&gt;&#10;&lt;li&gt;구성요소 : 커널, 쉘, 응용 프로그램&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;파일의 특징&#10;&lt;ul&gt;&#10;&lt;li&gt;파일의 이름(확장자)&#10;&lt;ul&gt;&#10;&lt;li&gt;exe, txt, zip, egg, etc. -&amp;gt; 4D 5A -&amp;gt; 윈도우에서 실행파일 일 경우 binary의 시작&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;파일의 경로&#10;&lt;ul&gt;&#10;&lt;li&gt;다양하게 지정할 수 있는 파일의 경로&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="2-vmwareworkstation--가상화에-관련된-회사-이름"&gt;2. VMware(workstation) : 가상화에 관련된 회사 이름&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;정의&#10;&lt;ul&gt;&#10;&lt;li&gt;하이퍼바이저 기반 가상 머신 소프트웨어&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;하이퍼바이저&#10;&lt;ul&gt;&#10;&lt;li&gt;가상 머신을 만들어주는 프로그램&lt;/li&gt;&#10;&lt;li&gt;HOST에서 GUEST를 만들어주는 프로그램&lt;/li&gt;&#10;&lt;li&gt;현재 사용하려는 workstation이 하이퍼바이저&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;실습&#10;&lt;ul&gt;&#10;&lt;li&gt;vmware 설치&lt;/li&gt;&#10;&lt;li&gt;가상 머신 생성&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="3-네트워크"&gt;3. 네트워크&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;정의&#10;&lt;ul&gt;&#10;&lt;li&gt;노드들이 데이터를 공유할 수 있게 하는 디지털 전기 통신망의 하나이다.&lt;/li&gt;&#10;&lt;li&gt;분산되어 있는 컴퓨터를 통신망으로 연결한 것을 말한다.&lt;/li&gt;&#10;&lt;li&gt;네트워크에서 여러 장치들은 노드 간 연결을 사용하여 서로에게 데이터를 교환한다.&lt;/li&gt;&#10;&lt;li&gt;*노드 : 네트워크에 속한 컴퓨터 또는 통신 장비&lt;/li&gt;&#10;&lt;li&gt;네트워크? 인터넷? www?&lt;br&gt;&#10;가장 큰 네트워크 인터넷&lt;br&gt;&#10;www : world wide WEB&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;분류&#10;&lt;ul&gt;&#10;&lt;li&gt;크기에 따른 분류&#10;&lt;ul&gt;&#10;&lt;li&gt;LAN, WAN, MAN, 기타&lt;/li&gt;&#10;&lt;li&gt;LAN : 가까운 지역을 하나로&lt;/li&gt;&#10;&lt;li&gt;WAN : 멀리 있는 지역을 하나로&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;연결 형태에 따른 분류&#10;&lt;ul&gt;&#10;&lt;li&gt;Star 형 : 중앙 장비에 모든 노드가 연결된 형태&lt;/li&gt;&#10;&lt;li&gt;Mesh 형 : 여러 노드들이 서로 그물처럼 연결된 형태&lt;/li&gt;&#10;&lt;li&gt;혼합형(Star + Mesh)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;통신 방식&#10;&lt;ul&gt;&#10;&lt;li&gt;유니 캐스트 : 1:1 통신&lt;/li&gt;&#10;&lt;li&gt;멀티 캐스트 : 1:다수 통신&lt;/li&gt;&#10;&lt;li&gt;브로드 캐스트 : 같은 네트워크(Local)에 있는 모든 대상에게 통신&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;프로토콜&#10;&lt;ul&gt;&#10;&lt;li&gt;정의 : 일종의 양식, 네트워크에서 노드와 노드가 통신할 때 어떤 노드가 어느 노드에게 어떤 데이터를 보내는지 작성하기위한 양식&lt;/li&gt;&#10;&lt;li&gt;가까운 곳으로 통신 : Ethernet 프로토콜(MAC 주소)&lt;/li&gt;&#10;&lt;li&gt;멀리 있는 곳으로 통신 : ICMP, IPv4, ARP(IP 주소)&lt;/li&gt;&#10;&lt;li&gt;여러가지 프로그램으로 통신 : TCP, UDP(port 번호)&lt;/li&gt;&#10;&lt;li&gt;여러 프로토콜들로 캡슐화 된 패킷(Ethernet/IPv4/TCP/데이터)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;실습&#10;&lt;ul&gt;&#10;&lt;li&gt;tracert [ip or address] : 네트워크 경로 추적&lt;br&gt;&#10;네트워크 장비 30개 이하로 연결되어 있다(30홉 이하)&lt;/li&gt;&#10;&lt;li&gt;wireshark : 네트워크 패킷을 볼 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="4-네트워크-모델"&gt;4. 네트워크 모델&lt;/h2&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/net_2/osi7.PNG" alt="IMAGE"&gt;&lt;/p&gt;</description></item><item><title>[D4] 2819</title><link>https://lameld.github.io/swea/2819/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/swea/2819/</guid><description>&lt;h1 id="격자판의-숫자-이어-붙이기"&gt;격자판의 숫자 이어 붙이기&lt;/h1&gt;&#10;&lt;p&gt;&lt;a href="https://swexpertacademy.com/main/code/problem/problemDetail.do"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;4 x 4 크기의 격자판이 있다. 격자판의 각 격자칸에는 0부터 9사이의 숫자가 적혀 있다.&lt;/li&gt;&#10;&lt;li&gt;격자판의 임의의 위치에서 시작한다.&lt;/li&gt;&#10;&lt;li&gt;동서남북 네 방향으로 인접한 격자로 총 6회 이동하여 각 칸에 숫자를 차례로 이어 붙인다.&lt;/li&gt;&#10;&lt;li&gt;이동을 할 때 중복을 허용한다.&lt;/li&gt;&#10;&lt;li&gt;0으로 시작하는 수도 만들 수 있다.&lt;/li&gt;&#10;&lt;li&gt;가능한 7자리 숫자의 개수를 구한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 풀이&lt;/p&gt;</description></item><item><title>1. 파이썬 프로그래밍의 기초, 자료형</title><link>https://lameld.github.io/python/ch01/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/python/ch01/</guid><description>&lt;h3 id="1-숫자형"&gt;1. 숫자형&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;숫자 형태로 이루어진 자료형&lt;/li&gt;&#10;&lt;li&gt;정수, 실수, 복소수, 8진수, 16진수 등&lt;/li&gt;&#10;&lt;li&gt;숫자형을 활용하기 위한 연산자&#10;&lt;ul&gt;&#10;&lt;li&gt;더하기, 빼기, 곱하기, 나누기, 나머지 연산&lt;/li&gt;&#10;&lt;li&gt;제곱을 나타내는 연산자 : &lt;code&gt;a**b&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;나눗셈 후 소수점 아랫자리를 버리는 연산자 : &lt;code&gt;7//4&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="2-문자열-자료형"&gt;2. 문자열 자료형&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문자, 단어 등으로 구성된 문자들의 집합&lt;/p&gt;</description></item><item><title>1장 : 깃 시작하기</title><link>https://lameld.github.io/gitstudy/ch1/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/gitstudy/ch1/</guid><description>&lt;h3 id="1-깃으로-무엇을-할-수-있을까"&gt;1. 깃으로 무엇을 할 수 있을까?&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;버전관리&#10;&lt;ul&gt;&#10;&lt;li&gt;local 저장소에 관련된 내용 :: git&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;백업하기&#10;&lt;ul&gt;&#10;&lt;li&gt;remote 저장소에 관련된 내용 :: github&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;협업하기&#10;&lt;ul&gt;&#10;&lt;li&gt;git, github 다루기&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-깃-설치하기"&gt;2. 깃 설치하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;기본적인 설치&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://git-scm.com/"&gt;깃 설치 사이트&lt;/a&gt;에서 설치할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;설치과정은 기본적으로 설정되어있는 것을 따라간다.&lt;/li&gt;&#10;&lt;li&gt;설치가 완료되면 윈도우 작업 표시줄의 검색 창에 &lt;code&gt;git&lt;/code&gt;이라고 입력한 후 검색 결과 중에서 &lt;code&gt;Git Bash&lt;/code&gt;를 누른다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git&lt;/code&gt;이라고 입력한 수 &lt;code&gt;enter&lt;/code&gt;를 눌러보면 깃 명령에서 사용할 수 있는 여러 옵션이 표시된다면 설치 성공이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;깃 환경 설정&#10;&lt;ul&gt;&#10;&lt;li&gt;사용자 설정을 위해 &lt;code&gt;git config&lt;/code&gt; 명령을 사용합니다. 여기서 &amp;ndash;global 옵션은 현재 컴퓨터에 있는 모든 저장소에서 같은 사용자 정보를 사용하도록 설정한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global user.name &amp;#34;사용자 이름&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global user.email 사용자@이메.일&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="3-리눅스-명령-연습"&gt;3. 리눅스 명령 연습&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;~ : 홈 디렉토리&lt;/li&gt;&#10;&lt;li&gt;pwd : 현재 작업 디렉토리&lt;/li&gt;&#10;&lt;li&gt;ls : 디렉토리 내용 확인&lt;/li&gt;&#10;&lt;li&gt;cd : 디렉토리 이동&lt;/li&gt;&#10;&lt;li&gt;. : 현재 디렉토리&lt;/li&gt;&#10;&lt;li&gt;.. : 상위 디렉토리&lt;/li&gt;&#10;&lt;li&gt;mkdir : 디렉토리 생성&lt;/li&gt;&#10;&lt;li&gt;rm : 파일 제거&#10;&lt;ul&gt;&#10;&lt;li&gt;rm -rf : 파일, 디렉토리를 가리지 않고 삭제(-r : recursive, -f : force)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;vim : 편집기&#10;&lt;ul&gt;&#10;&lt;li&gt;기본 편집기 변경하기&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git config -- global core.editor &amp;quot;notepad++&amp;quot;&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;touch : 빈 파일 생성&lt;/li&gt;&#10;&lt;li&gt;cat : 파일 내용 확인&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;cat [파일이름]&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;cat [파일1], [파일2], [파일3], ... , [파일n] &amp;gt; [새파일]&lt;/code&gt; : 파일n 개를 차례로 연결해서 새로운 파일을 만든다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;cat [파일1] &amp;gt;&amp;gt; [파일2]&lt;/code&gt; : 파일1의 내용을 파일2 끝에 연결한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>[2018] 캐시</title><link>https://lameld.github.io/kakao/2018_cache/</link><pubDate>Fri, 22 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2018_cache/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/17680"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;캐시 교체 알고리즘은 &lt;code&gt;LRU(Least Recently Used)&lt;/code&gt; 를 사용한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;cache hit&lt;/code&gt; 일 경우 실행시간은 1이다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;cache miss&lt;/code&gt; 일 경우 실행시간은 5이다.&lt;/li&gt;&#10;&lt;li&gt;총 실행 시간을 출력한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 풀이&lt;/p&gt;</description></item><item><title>[DS] Array</title><link>https://lameld.github.io/datastructure/dsarray/</link><pubDate>Fri, 15 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/datastructure/dsarray/</guid><description>&lt;h1 id="array배열"&gt;Array(배열)&lt;/h1&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;정적 배열 (Static Array)&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;기본적인 배열을 의미한다.&lt;/li&gt;&#10;&lt;li&gt;C++에서 간단하게 선언이 가능하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;1차원&lt;/p&gt;</description></item><item><title>컨넥트 스토리지 엔진</title><link>https://lameld.github.io/mariadb/engine-connect/</link><pubDate>Sun, 09 Apr 2023 00:00:00 +0000</pubDate><guid>https://lameld.github.io/mariadb/engine-connect/</guid><description>&lt;h2 id="특징"&gt;특징&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;기능을 제공하는 스토리지 엔진&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;다른 서버의 mariaDB 테이블과 연결&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;이기종 RDBMS의 테이블과 연결&lt;/p&gt;</description></item><item><title>3장 UNIX/Linux 기본 명령어와 개념</title><link>https://lameld.github.io/shell/ch03/</link><pubDate>Tue, 21 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/shell/ch03/</guid><description>&lt;p&gt;&lt;strong&gt;기본 리눅스 명령어가 익숙한 독자는 4장으로 가서 쉘 스크립트 작성에 관련된 기본 문법을 숙달하는 것을 추천한다.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>1-3 : 하드웨어 리소스</title><link>https://lameld.github.io/aws/ch01-3/</link><pubDate>Tue, 14 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/aws/ch01-3/</guid><description>&lt;h3 id="amazon-elastic-compute-cloudec2"&gt;Amazon Elastic Compute Cloud(EC2)&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;EC2&#10;&lt;ul&gt;&#10;&lt;li&gt;클라우드 위에서 가상 서버(인스턴스), 백업 이미지(AMI, 스냅샷), 디스크(EBS), 방화벽(보안 그룹), 고정 글로벌 IP(Elastic IP) 등을 사용할 수 있게 해주는 서비스&lt;/li&gt;&#10;&lt;li&gt;기본적인 사용 방법은 AWS가 제공하는 AMI를 기반으로 디스크 용량 또는 통신 요건을 설정해서 인스턴스를 생성하는 것이다.&lt;/li&gt;&#10;&lt;li&gt;인스턴스에 로그인해서 미들웨어 설치 또는 설정을 할 수 있으며, 백업이 필요한 시점에 AMI를 생성하거나, 필요에 따라 Elastic IP를 부여해서 인터넷과 통신할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;인스턴스&#10;&lt;ul&gt;&#10;&lt;li&gt;기존의 On Premise 환경 위의 서버에 해당한다.&lt;/li&gt;&#10;&lt;li&gt;인스턴스가 갖는 정보 : OS, CPU, 메모리&lt;/li&gt;&#10;&lt;li&gt;실제로 설치할 미들웨어 또는 저장할 데이터는 EBS에 저장된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;선택할 수 있는 OS의 종류&#10;&lt;ul&gt;&#10;&lt;li&gt;RedHat Enterprise Linux&lt;/li&gt;&#10;&lt;li&gt;SUSE Linux Enterprise Server&lt;/li&gt;&#10;&lt;li&gt;Ubuntu&lt;/li&gt;&#10;&lt;li&gt;Fedora&lt;/li&gt;&#10;&lt;li&gt;Debian&lt;/li&gt;&#10;&lt;li&gt;CentOS&lt;/li&gt;&#10;&lt;li&gt;Gentoo Linux&lt;/li&gt;&#10;&lt;li&gt;Oracle Linux&lt;/li&gt;&#10;&lt;li&gt;FreeBSD&lt;/li&gt;&#10;&lt;li&gt;Windows Server&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;인스턴스에 적용할 수 있는 인스턴스 유형&#10;&lt;ul&gt;&#10;&lt;li&gt;인스턴스 유형이란 인스턴스에 적용할 CPU, 메모리, 내장 디스트, 네트워크 용량 패턴을 나타낸다.&lt;/li&gt;&#10;&lt;li&gt;사용 목정에 따라 구분된다.&#10;&lt;ul&gt;&#10;&lt;li&gt;범용 T2 인스턴스와 M3 인스턴스&lt;/li&gt;&#10;&lt;li&gt;CPU 성능을 높게 설정한 C3 인스턴스와 C4 인스턴스&lt;/li&gt;&#10;&lt;li&gt;메모리 용량을 크게 설정한 R3 인스턴스&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;인스턴스 스토리지&#10;&lt;ul&gt;&#10;&lt;li&gt;EC3 인스턴스가 가동되는 물리 서버에 있는 로컬 디스크를 나타낸다.&lt;/li&gt;&#10;&lt;li&gt;인스턴스 유형에 따라 사용할 수 있는 인스턴스 스토리지의 크기와 개수가 정해진다.&lt;/li&gt;&#10;&lt;li&gt;인스턴스 스토리지를 사용할 때 주의해야 하는 것은 인스턴스 스토리지에 있는 데이터는 EC2 인스턴스를 중지하면 사라진다는 것이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;EBS-Backed 인스턴스와 Instance Store-Backed 인스턴스&#10;&lt;ul&gt;&#10;&lt;li&gt;EBS-Backed 인스턴스&#10;&lt;ul&gt;&#10;&lt;li&gt;OS를 포함한 루트 디바이스 정보를 EBS에 저장한 인스턴스를 나타낸다.&lt;/li&gt;&#10;&lt;li&gt;AWS는 EBS-Backed 인스턴스를 권장하고 있다.&lt;/li&gt;&#10;&lt;li&gt;EC2 인스턴스의 가동 중인 루트 장치와 관련된 변경 사항이 모두 EBS에 기록되므로, 인스턴스를 정지해도 변경 사항이 유지된다.&lt;/li&gt;&#10;&lt;li&gt;변경 내용이 반영된 상태로 인스턴스를 기동할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Instance Store-Backed 인스턴스&#10;&lt;ul&gt;&#10;&lt;li&gt;OS를 포함한 루트 디바이스 정보를 S3에 저장한 인스턴스를 나타낸다.&lt;/li&gt;&#10;&lt;li&gt;인스턴스 기동 때는 S3에서 인스턴스 스토리지에 데이터를 복사하고 기동한다.&lt;/li&gt;&#10;&lt;li&gt;이후에 다시 기동하면 S3에서 루트 디바이스를 처음부터 읽어 들이므로, 이전 변경 사항은 모두 파기된다.&lt;/li&gt;&#10;&lt;li&gt;루트 장치의 내용을 변경하고 싶다면 전용 도구를 사용해서 변경 후의 내용을 S3에 업로드해야 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;인스턴스 비용&#10;&lt;ul&gt;&#10;&lt;li&gt;인스턴스 유형에 따른 가격과 시간을 곱하면 구할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;예시&#10;&lt;ul&gt;&#10;&lt;li&gt;r2.small 인스턴스를 10일 동안 사용하면 다음과 같이 계산한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$0.04/시간 * 24시간 * 10일 = $9.6&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;인스턴스가 1시간을 넘지 않는 시간만큼 가동해도 1시간 만큼의 비용이 발생한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;인스턴스 비용 최적화&#10;&lt;ul&gt;&#10;&lt;li&gt;인스턴스의 활용 목적을 분명하게 해서 인스턴스 유형과 가동 시간을 조절해야 한다.&lt;/li&gt;&#10;&lt;li&gt;인스턴스를 지정한 날짜에 가동해서 처리하는 것은 AWS가 제공하는 CLI 또는 API를 활용해 쉽게 자동화할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;EC2 인스턴스에서 사용하는 OS 라이선스&#10;&lt;ul&gt;&#10;&lt;li&gt;OS 라이선스 비용은 EC2 사용 비용에 포함되어 있다.&lt;/li&gt;&#10;&lt;li&gt;선택한 OS에 따라서 같은 인스턴스 유형이라도 시간당 비용이 다를 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="amazon-elastic-block-storeebs"&gt;Amazon Elastic Block Store(EBS)&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;EBS 볼륨 유형&#10;&lt;ul&gt;&#10;&lt;li&gt;범용(SSD)&#10;&lt;ul&gt;&#10;&lt;li&gt;1GB마다 3IOPS의 베이스 퍼포먼스를 가진다.&lt;/li&gt;&#10;&lt;li&gt;IOPS를 직접적으로 지정할 수는 없지만, 용량이 늘어나면 자동으로 IOPS도 올라간다.&lt;/li&gt;&#10;&lt;li&gt;스토리지에 대한 읽고 쓰기는 비용이 추가되지 않는다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;프로비저닝된 IOPS(SSD)&#10;&lt;ul&gt;&#10;&lt;li&gt;최대 4000IOPS까지 I/O 성능을 지정할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;굉장히 빈번하게 I/O가 지속적으로 발생할 때 프로비저닝된 IOPS를 사용한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;마그네틱&#10;&lt;ul&gt;&#10;&lt;li&gt;기존의 마그네틱 디스크에 해당한다.&lt;/li&gt;&#10;&lt;li&gt;AWS가 SSD를 지원하기 시작한 이후로는 권장하지 않고 있다.&lt;/li&gt;&#10;&lt;li&gt;SSD에 비교해서 스토리지 비용이 싸므로, 개발 환경 등에 조금만 활용하는 경우에 적합하다.&lt;/li&gt;&#10;&lt;li&gt;읽고 쓰는 것에 대해서 비용일 발생하므로 주의가 필요하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;EBS 비용&#10;&lt;ul&gt;&#10;&lt;li&gt;인스턴스 유형에 따른 가격, 용량, 시간을 곱하면 구할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;예시&#10;&lt;ul&gt;&#10;&lt;li&gt;서울 리전에서 범용(SSD)을 10GB만큼 10일 사용하면 다음과 같이 계산한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$0.12/(1GB/월) * 10GB / 30일(1개월) * 10일 = $0.4&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;EBS 크기 변경&#10;&lt;ul&gt;&#10;&lt;li&gt;EBS의 크기를 변경하려면 이후에 설명하는 EBS 스냅샷을 생성해야한다.&lt;/li&gt;&#10;&lt;li&gt;생성한 EBS 스냅샷을 기반으로 EBS를 복구하게 만들고, 이때 크기를 변경해서 저장하면 된다.&lt;/li&gt;&#10;&lt;li&gt;EBS 크기를 변경할 때 용량 크기를 늘릴 수 있지만, 감소시킬 수 없다는 것에 주의가 필요하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;EBS 암호화&#10;&lt;ul&gt;&#10;&lt;li&gt;EBS를 새로 생성할 때 암호화 옵션을 활성화할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;암호화 방식은 AWS가 관리하는 암호 키(SSE-S3)를 활용한 AES-256 알고리즘을 사용하고 있다.&lt;/li&gt;&#10;&lt;li&gt;암호화 옵션을 활성화한 EBS는 인스턴스에 Attach하면, 읽고 쓰는 데이터들을 암호화하게 된다.&lt;/li&gt;&#10;&lt;li&gt;암호화 옵션을 사용한 EBS를 기반으로 만든 스냅샷(백업 기능)을 기반으로 복구하면 자동적으로 암호화 옵션이 활성화되며, 원래 EBS와 같은 키로 암호화 된다.&lt;/li&gt;&#10;&lt;li&gt;주의 사항&#10;&lt;ul&gt;&#10;&lt;li&gt;암호화 옵션을 활성화하지 않고 만든 EBS는 이후에 암호화 옵션을 활성화할 수 없음&lt;/li&gt;&#10;&lt;li&gt;암호화 옵션을 활성화한 스냅샷은 다른 AWS 계정과 공유할 수 없음&lt;/li&gt;&#10;&lt;li&gt;암호화 옵션을 사용하는 인스턴스 유형에만 사용할 수 있음&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;EC2, EBS의 SLA&#10;&lt;ul&gt;&#10;&lt;li&gt;EC2, EBS는 2013년 6월에 SLA(Service Level Agreement : 품질 서비스)를 발표했다.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="http://aws.amazon.com/lo/ec2/sla/"&gt;관련 디테일&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="ec2-백업"&gt;EC2 백업&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;EC2 백업&#10;&lt;ul&gt;&#10;&lt;li&gt;EC2 인스턴스 또는 EBS를 운용할 때 빼놓을 수 없는 것은 AMI와 EBS 스냅샷이라는 백업이다.&lt;/li&gt;&#10;&lt;li&gt;인스턴스 또는 EBS로부터 AMI, EBS 스냅샷을 생성하면, 언제든지 해당 시점으로 복구할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;리전 간의 복사, AWS 계정간의 공유, Auto Scaling에도 활용할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Amazon Machine Image(AMI)&#10;&lt;ul&gt;&#10;&lt;li&gt;가상 서버에 있는 인스턴스 기동에 필요한 정보를 저장하고 있다.&lt;/li&gt;&#10;&lt;li&gt;AMI 정보에는 OS, 아키텍처(32, 64bit), 가상화 방식(HVM, paravirtual), 인스턴스 기동 때에 Attach할 EBS 스냅샷 정보, 블록 디바이스 매핑 지점 등이 포함되어 있다.&lt;/li&gt;&#10;&lt;li&gt;AMI는 단독으로 인스턴스를 생성하지 못하며, EBS 스냅샷과 함께 사용해야 인스턴스를 생성할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;EBS 스냅샷&#10;&lt;ul&gt;&#10;&lt;li&gt;EBS를 백업해서 S3에 저장하는 기능이다.&lt;/li&gt;&#10;&lt;li&gt;백업 방식은 이전의 EBS 스냅샷에서 변경된 현재 EBS의 변경 사항만 백업하는 증분 백업이다.&lt;/li&gt;&#10;&lt;li&gt;변경 사항이 많을수록 EBS 스냅샷을 생성하는데 오랜 시간이 걸린다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;AMI, EBS 스냅샷의 리전 간 복사&#10;&lt;ul&gt;&#10;&lt;li&gt;AMI와 EBS 스냅샷은 다른 리전으로 복사해서 사용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;이런 기능을 활성화하면 여러 리전을 사용한 DR 환경을 쉽게 구현할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;AMI, EBS 스냅샷의 AWS 계정간 공유&#10;&lt;ul&gt;&#10;&lt;li&gt;AMI와 EBS 스냅샷은 공유할 AWS 계정 번호를 등록해서 같은 리전 내부에서 다른 AWS 계정과 공유할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;AMI를 공유하면 AMI 정보에 포함된 EBS 스냅샷도 공유된다.&lt;/li&gt;&#10;&lt;li&gt;특정 AWS 계정 뿐만 아니라 같은 리전 내부의 모든 AWS 사용자에게 AMI, EBS 스냅샷을 공개할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;주의 사항&#10;&lt;ul&gt;&#10;&lt;li&gt;AWS 계정 공유는 같은 리전 내부에서만 이루어지므로, 다른 리전과 공유할 때는 이전에 언급한 리전 간의 복사 조작을 사용해야 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;AMI, EBS 스냅샷 비용&#10;&lt;ul&gt;&#10;&lt;li&gt;AMI에는 비용이 들지 않는다.&lt;/li&gt;&#10;&lt;li&gt;EBS 스냅샷에서 비용이 발생한다.&lt;/li&gt;&#10;&lt;li&gt;예시&#10;&lt;ul&gt;&#10;&lt;li&gt;서울 리전에서 10GB로 10일동안 사용하면 다음과 같이 계산한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$0.005/월1GB * 10GB / 30일(1개월) * 10일 = $0.17&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="amazon-simple-storage-services3"&gt;Amazon Simple Storage Service(S3)&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;S3&#10;&lt;ul&gt;&#10;&lt;li&gt;99%의 내구성을 실현한 스토리지다.&lt;/li&gt;&#10;&lt;li&gt;REST, SOAP와 같은 단순 웹 서비스 인터페이스를 사용한다.&lt;/li&gt;&#10;&lt;li&gt;저장하는 데이터 양에 대한 비용도 저렴하고, 저장할 수 있는 데이터 양이 무한에 가깝다.&lt;/li&gt;&#10;&lt;li&gt;FTP 서버처럼 단순 파일 저장 영역으로 사용할 수도 있으며, 다양한 AWS 서비스 사용 로그 저장, 정적 웹 사이트 호스팅 기능 등도 가지고 있다.&lt;/li&gt;&#10;&lt;li&gt;비용 체계와 사용 방법이 다르긴 하지만, 이전 절에 설명한 EBS 스냅샷의 저장 영역으로도 사용되고 있다.&lt;/li&gt;&#10;&lt;li&gt;빅 데이터 분석 데이터 소스로 활용하거나 On Premise 환경의 재난 복구 전용 데이터 백업, Auto Scaling을 활용한 EC2 인스턴스의 로그 저장 등으로 폭 넓게 활용할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;S3 확장화 구성&#10;&lt;ul&gt;&#10;&lt;li&gt;S3는 데이터를 저장할 때 자동적으로 여러 개의 데이터 센터에서 데이터를 동기화한다.&lt;/li&gt;&#10;&lt;li&gt;높은 견고성과 내결함성을 보장한다.&lt;/li&gt;&#10;&lt;li&gt;동기 처리는 S3에서 실행한 업데이트 작업은 시간이 어느 정도 지나면 반드시 반영한다는 최동 일관성(eventual consistency)을 채용하고 잇따.&lt;/li&gt;&#10;&lt;li&gt;데이터를 저장한 뒤에 여러 데이터 센터에서 동기화 하는 동안 데이터 읽기를 해버리면, 데이터 동기화가 완료되지 않은 데이터 센터의 데이터를 참조했을 때 이전 데이터를 읽을 가능성이 있으므로 주의해야 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;S3 버킷 객체의 개념&lt;/li&gt;&#10;&lt;li&gt;S3의 스토리지 옵션&lt;/li&gt;&#10;&lt;li&gt;S3 비용&lt;/li&gt;&#10;&lt;li&gt;S3 암호화&lt;/li&gt;&#10;&lt;li&gt;S3 접근 관리&lt;/li&gt;&#10;&lt;li&gt;S3 이벤트 알림&lt;/li&gt;&#10;&lt;li&gt;S3의 SLA&lt;/li&gt;&#10;&lt;li&gt;S3의 웹 호스팅 기능&lt;/li&gt;&#10;&lt;li&gt;EBS 스냅샷과 S3 객체의 차이&lt;/li&gt;&#10;&lt;li&gt;S3의 버전 관리&lt;/li&gt;&#10;&lt;li&gt;S3 수명 주기 설정&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="amazon-glacier"&gt;Amazon Glacier&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Glacier 비용&lt;/li&gt;&#10;&lt;li&gt;Glacier의 SLA&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>프로그래머스 C++ 풀이 목록</title><link>https://lameld.github.io/algorithms/programmers-cpp/</link><pubDate>Tue, 07 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/algorithms/programmers-cpp/</guid><description>&lt;p&gt;&lt;a href="https://github.com/LaMelD/algorithms/tree/master/cpp/Programmers"&gt;algorithms/cpp/Programmers&lt;/a&gt;에 있는 프로그래머스 풀이 목록이다. C++ 풀이 154문제와 SQL 풀이 28문제를 레벨별로 나눴다. 항목을 누르면 풀이 파일로 간다.&lt;/p&gt;</description></item><item><title>CH03. 컨테이너 실전 구축 및 배포</title><link>https://lameld.github.io/docker/ch-03/</link><pubDate>Fri, 03 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-03/</guid><description>&lt;h2 id="1-어플리케이션과-시스템-내-단일-컨테이너의-적정-비중"&gt;1. 어플리케이션과 시스템 내 단일 컨테이너의 적정 비중&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;header&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;도커를 사용해 시스템을 구축한다는 것 = 자신이 만든 어플 컨테이너 + 공개된 어플/미들웨어 컨테이너&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;컨테이너 1개 = 프로새스 1개?&lt;/p&gt;</description></item><item><title>Network Device</title><link>https://lameld.github.io/cloudbasic/network_device/</link><pubDate>Mon, 06 Jan 2020 09:34:37 +0900</pubDate><guid>https://lameld.github.io/cloudbasic/network_device/</guid><description>&lt;h3 id="200106-monday--200110-friday"&gt;200106 Monday ~ 200110 Friday&lt;/h3&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-계층별-장비와-케이블"&gt;1. 계층별 장비와 케이블&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;계층 별 장비&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Physical Layer &amp;ndash;&amp;gt; Repeater, Hub&lt;/li&gt;&#10;&lt;li&gt;Data link Layer &amp;ndash;&amp;gt; Switch, Bridge&lt;/li&gt;&#10;&lt;li&gt;Network Layer &amp;ndash;&amp;gt; Router, L3 Switch&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Physical Layer :: Repeater&lt;/p&gt;</description></item><item><title>2. 프로그램의 구조를 쌓는다! 제어문</title><link>https://lameld.github.io/python/ch02/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/python/ch02/</guid><description>&lt;h3 id="1-if문"&gt;1. if문&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;형식&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;조건문&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# if의 조건식이 True일 때&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 실행문&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;조건문&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# elif의 조건식이 True일 때&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 실행문&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 위의 조건식이 True인 것이 없을 때&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 실행문&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://lameld.github.io/images/if_elif.PNG" alt="ifelif"&gt;&lt;/p&gt;</description></item><item><title>2장 : 깃으로 버전 관리하기</title><link>https://lameld.github.io/gitstudy/ch2/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/gitstudy/ch2/</guid><description>&lt;h3 id="1-깃-저장소"&gt;1. 깃 저장소&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;깃 초기화 하기&#10;&lt;ul&gt;&#10;&lt;li&gt;디렉토리를 하나 새로 만들고 내부를 살펴본 뒤 &lt;code&gt;git init&lt;/code&gt;을 하면 &lt;code&gt;.git&lt;/code&gt;이라는 디렉토리가 새로 생긴다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;.git&lt;/code&gt; : 깃을 사용하면 버전이 저장될 &amp;lsquo;저장소&amp;rsquo;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir hi-git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd hi-git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -al&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -al&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-버전-만들기"&gt;2. 버전 만들기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;깃에서 버전이란&#10;&lt;ul&gt;&#10;&lt;li&gt;문서를 수정하고 저장할 때마다 생기는 것&lt;/li&gt;&#10;&lt;li&gt;원래 파일 이름은 그대로 유지하면서 파일에서 무엇을 변경했는지를 변경 시점마다 저장할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;각 버전마다 작업했던 내용을 확인할 수 있고, 그 버전으로 rollback할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;스테이지와 커밋 이해하기&#10;&lt;ul&gt;&#10;&lt;li&gt;작업트리 :: workspace&#10;&lt;ul&gt;&#10;&lt;li&gt;파일 수정, 저장 등의 작업을하는 디렉토리&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;스테이지 :: index&#10;&lt;ul&gt;&#10;&lt;li&gt;버전으로 만들 파일이 대기하는 곳&lt;/li&gt;&#10;&lt;li&gt;명령어&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add [파일 또는 디렉토리]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;저장소 :: local repository&#10;&lt;ul&gt;&#10;&lt;li&gt;스테이지에 대기하고 있던 파일들을 버전으로 만들어 저장하는 곳&lt;/li&gt;&#10;&lt;li&gt;명렁어&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;커밋 메시지 입력&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;순서&lt;br&gt;&#10;1.작업트리에서 작업을 한다.&lt;br&gt;&#10;2.작업물을 스테이지에 올린다.&lt;br&gt;&#10;3.스테이지에 있는 모든 것을 로컬 저장소에 저장한다.&lt;/li&gt;&#10;&lt;li&gt;스테이징과 커밋 한꺼번에 처리하기&#10;&lt;ul&gt;&#10;&lt;li&gt;한 번이라도 커밋한 적이 있는 파일을 다시 커밋할 때 사용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git commit -am &amp;quot;커밋 메시지&amp;quot;&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;현재 깃 상태 확인 :: git status&lt;/li&gt;&#10;&lt;li&gt;깃의 로그 확인 :: git log&#10;&lt;ul&gt;&#10;&lt;li&gt;여러가지 옵션을 줄 수 있다.&lt;/li&gt;&#10;&lt;li&gt;대표적인 옵션 :: &amp;ndash;oneline, &amp;ndash;branches, &amp;ndash;graph&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;변경 사항 확인하기 :: git diff&#10;&lt;ul&gt;&#10;&lt;li&gt;작업 디렉토리와 저장소의 차이를 볼 수 있다.&lt;br&gt;&#10;&lt;img src="https://lameld.github.io/images/work.PNG" alt="이미지 대체"&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;버전 만드는 단계마다 파일 상태 알아보기&#10;&lt;ul&gt;&#10;&lt;li&gt;tracked 파일과 untracked 파일&#10;&lt;ul&gt;&#10;&lt;li&gt;untracked 파일 :: 한번도 깃에서 버전 관리를 하지 않았기 때문에 수정 내역을 추적하지 않음.&lt;/li&gt;&#10;&lt;li&gt;tracked 파일 :: untracked 파일이 아닌 파일&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;unmodified, modified, staged 상태&#10;&lt;ul&gt;&#10;&lt;li&gt;tracked 파일의 상태 확인&lt;/li&gt;&#10;&lt;li&gt;unmodified : 커밋된 이후 수정되지 않은 상태&lt;/li&gt;&#10;&lt;li&gt;modified : 커밋된 이후 수정된 상태&lt;/li&gt;&#10;&lt;li&gt;staged : modified 상태에서 &lt;code&gt;git add [파일 또는 폴더]&lt;/code&gt;를 실시하여 스테이지에 올려놓은 상태(커밋 직전의 상태)&lt;/li&gt;&#10;&lt;li&gt;커밋을 실시하면 unmodified 상태로 돌아간다.&lt;br&gt;&#10;&lt;img src="https://lameld.github.io/images/untracked.PNG" alt="이미지 대체"&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;.gitignore 파일로 버전 관리에서 제외하기!&#10;&lt;ul&gt;&#10;&lt;li&gt;버전 관리 중인 디렉토리 안에 버전관리를 하지 않을 특정 파일 또는 디렉토리가 있다면 .gitignore 파일을 만들어 목록을 지정할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;예시&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat .gitignore&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mynote.txt # 파일을 ignore&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;temp/ # 폴더를 ignore&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.swp # 확장자를 ignore&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;작업 되돌리기(Rollback)&#10;&lt;ul&gt;&#10;&lt;li&gt;작업트리에서 수정한 파일 되돌리기 :: &lt;code&gt;git checkout -- [수정한 파일]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;checkout으로 되돌린 내용은 다시 복구할 수 없습니다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;스테이징 되돌리기 :: &lt;code&gt;git reset HEAD [파일이름]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;수정된 파일을 스테이징 했을 때, 스테이징을 취소한는 방법&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;최신 커밋 되돌리기 :: &lt;code&gt;git reset HEAD^&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;가장 마지막에 한 커밋을 취소하는 방법&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git reset&lt;/code&gt; 명령의 옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git reset --soft HEAD^&lt;/code&gt; : 최근 커밋을 하기 전 상태로 작업 트리를 되돌립니다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git reset --mixed HEAD^&lt;/code&gt; : 최근 커밋과 스테이징을 하기 전 상태로 작업 트리를 되돌린다. 기본값&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git reset --hard HEAD^&lt;/code&gt; : 최근 커밋과 스테이징, 파일 수정을 하기 전 상태로 작업 트리를 되돌린다. 되돌린 내용은 복구 불가능&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;HEAD^&lt;/code&gt; 부분에 &lt;code&gt;커밋해시&lt;/code&gt;를 넣어주면 특정 커밋 상태로 되돌아갈 수 있습니다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;특정 커밋으로 되돌아간다면 그 이후의 버전을 삭제할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;버전 삭제하지 않고 되돌리기 :: &lt;code&gt;git revert [커밋 해쉬를 넣는다]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;나중에 사용할 것을 대비해서 커밋을 되돌리더라도 취소한 커밋을 남겨두어야 할 때가 있다.&lt;/li&gt;&#10;&lt;li&gt;이때는 &lt;code&gt;git reset&lt;/code&gt;이 아닌 &lt;code&gt;git revert&lt;/code&gt;를 사용한다.&lt;br&gt;&#10;&lt;img src="https://lameld.github.io/images/work.PNG" alt="이미지 대체"&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>[2018] 다트 게임</title><link>https://lameld.github.io/kakao/2018_dart/</link><pubDate>Thu, 21 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2018_dart/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/17682"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;규칙&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;다트 게임은 총 3번의 기회로 구성된다.&lt;/li&gt;&#10;&lt;li&gt;각 기회마다 얻을 수 있는 점수는 0 ~ 10점까지이다.&lt;/li&gt;&#10;&lt;li&gt;점수와 함께 S(점수의 1승), D(점수의 2승), T(점수의 3승)가 주어진다.&lt;/li&gt;&#10;&lt;li&gt;옵션으로 *(해당 점수와 이전에 얻은 점수를 각각 2배로 한다), #(해당 점수를 마이너스한다)이 존재한다.&lt;/li&gt;&#10;&lt;li&gt;*는 첫번째 기회에도 등장할 수 있으며, 이 때 해당점수만 2배로 한다.&lt;/li&gt;&#10;&lt;li&gt;*, #은 둘 중 하나만 존재하거나 존재하지 않을 수 있다.&lt;/li&gt;&#10;&lt;li&gt;S, D, T는 점수마다 하나씩 존재한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;입력 형식 : 1S2D*3T(점수 | 보너스 | [ 옵션 ] )&lt;/p&gt;</description></item><item><title>[DS] Single Linked List</title><link>https://lameld.github.io/datastructure/dslinkedlist/</link><pubDate>Fri, 15 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/datastructure/dslinkedlist/</guid><description>&lt;h1 id="single-linked-list-단순-연결-리스트"&gt;Single Linked List (단순 연결 리스트)&lt;/h1&gt;&#10;&lt;h3 id="1-개념"&gt;1. 개념&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;하나의 노드에 필요한 정보를 담고 다음에 해당하는 노드를 가리키고 있는 자료구조로 포인터를 이용해 자료들을 선형으로 연결한 자료구조이다.&lt;/li&gt;&#10;&lt;li&gt;[ 배열 ] 과 비교했을 때 추가 및 삭제가 쉽다는 장점이 있지만 접근할 때 O(n)만큼 걸린다는 단점이 있습니다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="2-구현"&gt;2. 구현&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;List를 구성할 노드를 생성하고 기본적인 기능을 추가합니다.&#10;&lt;ul&gt;&#10;&lt;li&gt;private 멤버 변수&#10;&lt;ul&gt;&#10;&lt;li&gt;data : 노드의 값&lt;/li&gt;&#10;&lt;li&gt;pnext : 현재 노드의 다음을 알려주는 포인터&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;public 멤버 함수&#10;&lt;ul&gt;&#10;&lt;li&gt;Node(), Node(T) : 생성자&lt;/li&gt;&#10;&lt;li&gt;getData() : 노드의 data를 리턴한다.&lt;/li&gt;&#10;&lt;li&gt;setData() : 노드의 data를 설정한다.&lt;/li&gt;&#10;&lt;li&gt;getNext() : 현재 노드의 다음 노드를 리턴한다.&lt;/li&gt;&#10;&lt;li&gt;setNext() : 현재 노드의 다음 노드를 설정한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt; &lt;span class="n"&gt;pnext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;singlenode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt; &lt;span class="n"&gt;getNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pnext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;singlenode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt; &lt;span class="n"&gt;pnode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pnext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pnode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pnext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pnext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;Node가 들어갈 List의 틀(class)을(를) 생성하고 필요한 기능과 멤버 변수를 추가해줍니다.&#10;&lt;ul&gt;&#10;&lt;li&gt;private 멤버 변수&#10;&lt;ul&gt;&#10;&lt;li&gt;phead : List의 가장 앞 부분을 알려준다.&lt;/li&gt;&#10;&lt;li&gt;ptail : List의 끝을 알려준다.&lt;/li&gt;&#10;&lt;li&gt;ssize : List에 들어있는 노드의 갯수를 알려준다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;public 멤버 함수&#10;&lt;ul&gt;&#10;&lt;li&gt;SingleLinkedList() : 생성자&lt;/li&gt;&#10;&lt;li&gt;isEmpty() : List가 비어있다면 True, 아니면 False&lt;/li&gt;&#10;&lt;li&gt;size() : List에 들어있는 노드의 갯수를 리턴한다.&lt;/li&gt;&#10;&lt;li&gt;getHead() : List의 가장 앞 부분을 알려주는 phead를 리턴한다&lt;/li&gt;&#10;&lt;li&gt;getData(), AddFront(), AddBack(), InsertNode(), DeleteNode()&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SingleLinkedList&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt; &lt;span class="n"&gt;phead&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt; &lt;span class="n"&gt;ptail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ssize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;SingleLinkedList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;phead&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ssize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt; &lt;span class="n"&gt;getHead&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;phead&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddFront&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddBack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InsertNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;DeleteNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;멤버 함수 상세 내용&lt;/p&gt;</description></item><item><title>테이블</title><link>https://lameld.github.io/mariadb/object-table/</link><pubDate>Wed, 19 Apr 2023 00:00:00 +0000</pubDate><guid>https://lameld.github.io/mariadb/object-table/</guid><description>&lt;h2 id="개념"&gt;개념&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;테이블의 컬럼과 행&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컬럼(Column) : 테이블에 저장될 데이터의 특성을 지정&lt;/li&gt;&#10;&lt;li&gt;행(Row) : 컬럼에 정의된 형식으로 저장된 데이터를 의미&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ol start="2"&gt;&#10;&lt;li&gt;데이터 타입&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Number Data Type&lt;/p&gt;</description></item><item><title>SW Expert Academy 풀이 목록</title><link>https://lameld.github.io/algorithms/swea/</link><pubDate>Sun, 02 Aug 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/algorithms/swea/</guid><description>&lt;p&gt;&lt;a href="https://github.com/LaMelD/algorithms/tree/master/cpp/SWExpertAcademy"&gt;algorithms/cpp/SWExpertAcademy&lt;/a&gt;에 있는 SW Expert Academy C++ 풀이 86문제의 목록이다. 난이도(D2~D4)별로 나눴고, 번호를 누르면 풀이 파일로 간다. 풀이 과정을 적은 글은 &lt;a href="https://lameld.github.io/swea/"&gt;SW Expert Academy Solution&lt;/a&gt; 시리즈에 있다.&lt;/p&gt;</description></item><item><title>4장 쉘 프로그래밍 문법</title><link>https://lameld.github.io/shell/ch04/</link><pubDate>Wed, 22 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/shell/ch04/</guid><description>&lt;p&gt;&lt;strong&gt;Bourne Shell(sh)의 문법을 중심으로 설명한다.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>CH04. 스웜을 이용한 실전 어플리케이션 개발</title><link>https://lameld.github.io/docker/ch-04/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-04/</guid><description>&lt;h2 id="1-웹-어플리케이션-구성"&gt;1. 웹 어플리케이션 구성&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;어플리케이션의 요구 조건&#10;&lt;ul&gt;&#10;&lt;li&gt;TODO를 등록, 수정, 삭제할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;등록된 TODO의 목록을 출력할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;브라우저에서 사용할 수 있는 웹 어플리케이션이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;아키텍처&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;오케스트레이션 시스템은 도커 스웜 사용&lt;/p&gt;</description></item><item><title>Linux Basic</title><link>https://lameld.github.io/cloudbasic/linux_basic/</link><pubDate>Mon, 13 Jan 2020 10:31:27 +0900</pubDate><guid>https://lameld.github.io/cloudbasic/linux_basic/</guid><description>&lt;h3 id="200116-thurday--200116-thursday"&gt;200116 Thurday ~ 200116 Thursday&lt;/h3&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-linux리눅스"&gt;1. Linux(리눅스)&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;리눅스란?&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴퓨터 운영체제의 한 종류&lt;/li&gt;&#10;&lt;li&gt;윈도우와는 다르게 오픈 소스 운영체제&lt;/li&gt;&#10;&lt;li&gt;소스코드가 공개되어 있기 때문에 다양한 리눅스 기반의 운영체제가 존재&#10;&lt;ul&gt;&#10;&lt;li&gt;구글의 안드로이드도 리눅스를 기반으로 만든 운영체제&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;운영체제란?&lt;/p&gt;</description></item><item><title>3. 프로그램의 입력과 출력</title><link>https://lameld.github.io/python/ch03/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/python/ch03/</guid><description>&lt;h3 id="1-함수"&gt;1. 함수&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;입력값을 가지고 어떤 일을 수행한 다음에 그 결과물을 내어놓는 것.&lt;/li&gt;&#10;&lt;li&gt;코드의 재사용&lt;/li&gt;&#10;&lt;li&gt;반복적으로 사용되는 가치 있는 부분&lt;/li&gt;&#10;&lt;li&gt;파이썬 함수의 구조&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;함수명&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;입력&lt;/span&gt; &lt;span class="n"&gt;인수&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;수행할&lt;/span&gt; &lt;span class="n"&gt;문장1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;수행할&lt;/span&gt; &lt;span class="n"&gt;문장2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;함수명&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;입력&lt;/span&gt; &lt;span class="n"&gt;인수&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;수행할&lt;/span&gt; &lt;span class="n"&gt;문장&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;결과값&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;입력 인수가 없을 수 있다.&lt;/li&gt;&#10;&lt;li&gt;입력 인수가 여러 개일 수 있다.&lt;/li&gt;&#10;&lt;li&gt;결과값이 없는 함수일 수 있다.&lt;/li&gt;&#10;&lt;li&gt;입력 인수와 결과값이 둘 다 없는 함수일 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;입력값이 몇 개가 될지 모를 때(**)&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sum_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sum_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;입력값이 몇 개가 될지 모를 때(**)&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;{0}&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="si"&gt;{1}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;입력 인수에 초깃값 미리 설정하기&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;say_myself&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;man&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;나의 이름 &lt;/span&gt;&lt;span class="si"&gt;{0}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;나의 나이 &lt;/span&gt;&lt;span class="si"&gt;{0}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;man&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;남자&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;여자&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;say_myself&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Sam&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;say_myself&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Jane&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;함수 안에서 선언된 변수의 효력 범위&#10;&lt;ul&gt;&#10;&lt;li&gt;함수 안에서 선언된 변수는 함수 안에서 수명을 다한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;life&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;# 함수가 끝날 때 까지 a 는 2이다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# a 는 1이다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;life&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# a 는 1이다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;life&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;# 함수 외부에 있는 a에 직접 접근한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;life&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;life&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;# 결과값을 주고 a에 대입한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;life&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 호출과 대입&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="2-사용자-입력과-출력"&gt;2. 사용자 입력과 출력&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;사용자 입력&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;input()&lt;/code&gt;을 통해서 사용자에게 입력을 받을 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;출력&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;print()&lt;/code&gt;를 통해서 프롬프트에 출력할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ragne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;문자열 띄어쓰기는 콤마로 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;life&amp;#34;&amp;#34;is&amp;#34;&amp;#34;too &amp;#34;&amp;#34;short&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;life&amp;#34;&amp;#34;is&amp;#34;&amp;#34;too&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;short&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;life&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;is&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;too&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;short&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="3-파일-입출력"&gt;3. 파일 입출력&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;파일 생성&lt;/p&gt;</description></item><item><title>3장 : 깃과 브랜치</title><link>https://lameld.github.io/gitstudy/ch3/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/gitstudy/ch3/</guid><description>&lt;h3 id="1-브랜치branch"&gt;1. 브랜치(branch)&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;분기점&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/branch.PNG" alt="이미지"&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;master에서 commit한다.&lt;/li&gt;&#10;&lt;li&gt;현 상태에서 Feature-1 브랜치를 만들어 새로운 내용을 추가하여 commit한다.&lt;/li&gt;&#10;&lt;li&gt;master에서 새로운 내용을 넣어 commit한다.&lt;/li&gt;&#10;&lt;li&gt;현 상태에서 Feature-2 브랜치를 만들어 새로운 내용을 추가하여 commit 한다.&lt;/li&gt;&#10;&lt;li&gt;Feature-1과 master를 merge(병합)한다.&lt;/li&gt;&#10;&lt;li&gt;Feature-2와 master를 merge(병합)한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-브랜치-만들기"&gt;2. 브랜치 만들기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;실습 환경 설정하기&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir branchtest&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd branchtest&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;work 1&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;새로운 저장소를 만든다.&lt;/li&gt;&#10;&lt;li&gt;새로운 파일을 만들고 commit까지 실시한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;새 브랜치 만들기&#10;&lt;ul&gt;&#10;&lt;li&gt;브랜치 확인 :: &lt;code&gt;git branch&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;브랜치 생성 :: &lt;code&gt;git branch [브랜치 이름]&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch apple&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch ms&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch google&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;브랜치 이동하기 :: &lt;code&gt;git checkout [브랜치 이름]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;master에서 work.txt를 수정하고 커밋한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git log --oneline&lt;/code&gt;으로 로그를 보면 master와 다른 브랜치의 상태가 다른 것을 확인 할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;apple 브랜치로 이동하여 &lt;code&gt;git log --oneline&lt;/code&gt;으로 로그를 보면 HEAD가 apple를 가리키고 있는 것을 볼 수 있다.&lt;/li&gt;&#10;&lt;li&gt;work.txt를 cat으로 확인해보면 master에서 수정한 내용이 반영되지 않았음을 확인할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="3-브랜치-정보-확인하기"&gt;3. 브랜치 정보 확인하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;apple에서 work.txt를 수정하고 커밋한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git log --oneline --branches --graph&lt;/code&gt;를 한다면 분기되었음을 그래프로 확인할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git log master..apple&lt;/code&gt; : master 브랜치를 기준으로 apple과 비교하여 차이점을 알 수 있다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git log apple..master&lt;/code&gt; : apple 브랜치를 기준으로 master와 비교하여 차이점을 알 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="4-브랜치-병합하기"&gt;4. 브랜치 병합하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;서로 다른 파일 병합&#10;&lt;ul&gt;&#10;&lt;li&gt;새로운 저장소를 만든다.&lt;/li&gt;&#10;&lt;li&gt;work.txt 파일을 만들어 &amp;lsquo;1&amp;rsquo;을 입력하고 저장&lt;/li&gt;&#10;&lt;li&gt;add 해주고 commit을 실행하는데 메시지를 &amp;ldquo;work 1&amp;quot;으로 한다.&lt;/li&gt;&#10;&lt;li&gt;b1 브랜치를 생성해준다.&lt;/li&gt;&#10;&lt;li&gt;master 브랜치에서 master.txt 파일을 만들어 &amp;lsquo;master 2&amp;rsquo;를 입력하고 저장&lt;/li&gt;&#10;&lt;li&gt;&amp;ldquo;master work 2&amp;quot;라는 메시지와 함께 커밋&lt;/li&gt;&#10;&lt;li&gt;b1 브랜치로 이동하여 b1.txt 파일을 만들어 &amp;lsquo;b1 2&amp;rsquo;를 입력하고 저장&lt;/li&gt;&#10;&lt;li&gt;&amp;ldquo;b1 work 2&amp;quot;라는 메시지와 함께 커밋&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git log --oneline --branches --graph&lt;/code&gt;로 현재 상태를 확인한다.&lt;/li&gt;&#10;&lt;li&gt;master 브랜치로 이동하여 &lt;code&gt;git merge b1&lt;/code&gt;을 입력하여 병합한다. :: master 브랜치를 b1과 병합한 결과를 master 브랜치에 적용한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir man1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd man1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;work 1&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim master.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add master.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;master work 2&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim b1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add b1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;b1 work 2&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git log --oneline --branches --graph&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git merge b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -al&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;같은 파일 다른 위치 수정후 병합&#10;&lt;ul&gt;&#10;&lt;li&gt;새로운 저장소를 만든다.&lt;/li&gt;&#10;&lt;li&gt;work.txt 파일을 만들어 아래와 같이 입력하고 저장&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;add 해주고 commit을 실행하는데 메시지를 &amp;ldquo;work 1&amp;quot;으로 한다.&lt;/li&gt;&#10;&lt;li&gt;b1 브랜치를 생성해준다.&lt;/li&gt;&#10;&lt;li&gt;master 브랜치에서 work.txt 파일을 아래와 같이 수정하여 &amp;ldquo;master work 2&amp;rdquo; 메시지로 커밋한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;master content 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;b1 브랜치로 이동하여 work.txt 파일을 아래와 같이 수정하여 &amp;ldquo;b1 work 2&amp;rdquo; 메시지로 커밋한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;b1 content 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;master 브랜치로 이동하여 merge를 실시한 뒤 work.txt를 cat으로 확인하면 자연스럽게 합쳐진 모습을 볼 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init man2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd man2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;work 1&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -am &amp;#34;master work 2&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -am &amp;#34;b1 work 2&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git merge b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;같은 파일 같은 위치 수정후 병합&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;em&gt;&lt;strong&gt;깃에서는 줄 단위로 변경여부를 확인한다.&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;em&gt;&lt;strong&gt;같은 줄을 수정했을 때 브랜치를 병합하면 브랜치 충돌이 발생&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;&#10;&lt;li&gt;새로운 저장소를 만든다.&lt;/li&gt;&#10;&lt;li&gt;work.txt 파일을 만들어 아래와 같이 입력하고 저장&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;add 해주고 commit을 실행하는데 메시지를 &amp;ldquo;work 1&amp;quot;으로 한다.&lt;/li&gt;&#10;&lt;li&gt;b1 브랜치를 생성해준다.&lt;/li&gt;&#10;&lt;li&gt;master 브랜치에서 work.txt 파일을 아래와 같이 수정하여 &amp;ldquo;master work 2&amp;rdquo; 메시지로 커밋한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;master content 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;b1 브랜치로 이동하여 work.txt 파일을 아래와 같이 수정하여 &amp;ldquo;b1 work 2&amp;rdquo; 메시지로 커밋한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;b1 content 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#title&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;content&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;master 브랜치로 이동하여 merge를 실시하면 CONFLICT 메시지가 출려된다.&lt;/li&gt;&#10;&lt;li&gt;편집기로 work.txt를 열어서 필요없는 내용 &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;HEAD&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;b1&lt;/code&gt;, &lt;code&gt;=====&lt;/code&gt;을 삭제한 뒤 저장하고 편집기를 종료한다.&lt;/li&gt;&#10;&lt;li&gt;수정한 work.txt를 스테이지에 올리고 커밋하면 충돌을 해결하고 커밋한 것이다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git log --oneline --branches --graph&lt;/code&gt;로 지금까지 만든 브랜치와 커밋의 관계를 한눈에 확인할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init man2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd man2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;work 1&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -am &amp;#34;master work 2&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -am &amp;#34;b1 work 2&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git merge b1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim work.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -am &amp;#34;merge b1 branch&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git log --oneline --branches --graph&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;브랜치를 병합할 때 편집기&#10;&lt;ul&gt;&#10;&lt;li&gt;편집기 열리게 하기 : &lt;code&gt;git merge b1 --edit&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;편집기 열리지 않게 하기 : &lt;code&gt;git merge b1 --no-edit&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;병합 및 충돌 해결 프로그램&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;프로그램&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;설명&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;P4Merge&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;무료이고 직관적이며 사용이 편리하고 병합 기능이 뛰어남. 단축키가 지원되지 않는 단점이 있다.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Meld&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;무료이며 오픈소스. 파일을 비교하는 것뿐만 아니라 직접 편집할 수 있다.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Kdiff3&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;무료이고 사용이 편리하고 병합 기능이 뛰어나지만 한글이 깨져보일 수 있다.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Araxis Merge&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;유료지만 용량이 큰 파일에서도 잘 동작함&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;병합이 끝난 브랜치 삭제&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git branch&lt;/code&gt;로 남은 브랜치 확인&lt;/li&gt;&#10;&lt;li&gt;저장소의 기본 브랜치는 master 브랜치이므로 master 브랜치로 이동하여 브랜치를 삭제하는 것이 안전하다.&lt;/li&gt;&#10;&lt;li&gt;b1 브랜치의 삭제&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git branch -d b1&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git branch --delete b1&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git branch -D b1&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="5-브랜치-관리하기"&gt;5. 브랜치 관리하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;커밋 해시를 통해서 브랜치들을 관리하고 커밋 해시(버전)으로 rollback 할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;수정 중인 파일 감추기 및 되돌리기 :: &lt;code&gt;git stash&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;아직 커밋하지 않고 작업 중인 파일들을 잠시 감춰둘 수 있다.&lt;/li&gt;&#10;&lt;li&gt;stash 명령을 사용하기 위해선 파일이 tracked 상태여야 한다.(한 번은 커밋한 상태여야 한다)&lt;/li&gt;&#10;&lt;li&gt;새로운 저장소를 만들고 f1.txt, f2.txt를 생성하고 커밋한다.&lt;/li&gt;&#10;&lt;li&gt;f1.txt와 f2.txt를 수정하고 저장만 한 뒤 &lt;code&gt;git status&lt;/code&gt;로 상태를 확인한다.&lt;/li&gt;&#10;&lt;li&gt;각각의 파일이 modified 상태인 것을 확인 할 수있다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git stash&lt;/code&gt;를 실시하고 다시 &lt;code&gt;git status&lt;/code&gt;를 해보면 modified 메시지가 사라진 것을 확인 할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;같은 방법으로 여러 파일을 수정한 후 따로 보관할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;stash가 보관되는 공간은 stack으로 이루어져 LIFO이 적용된다.&#10;&lt;ul&gt;&#10;&lt;li&gt;가장 최근에 보관한 stash는 stash@{0}에 담기게 된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;감추어둔 파일을 꺼내와 계속 수정하거나 커밋할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;이때 가장 최근 항목을 되돌리기 위해서 &lt;code&gt;git stash pop&lt;/code&gt;을 사용한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init st&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd st&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim f1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim f2.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;add f1, f2&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim f1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim f2.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git stash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git stash pop&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;stash 관련 명령어&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git stash&lt;/code&gt; : stash 스택에 modified 상태의 작업물을 담는다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git stash pop&lt;/code&gt; : 가장 최근의 항목을 되돌리고 stash 스택에서 제거한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git stash list&lt;/code&gt; : stash 스택의 목록을 확인한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git stash apply&lt;/code&gt; : 가장 최근의 항목을 되돌리고 stash 스택에 남겨둔다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git stash drop&lt;/code&gt; : 가장 최근의 항목을 삭제한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>[2018] 뉴스 클러스터링</title><link>https://lameld.github.io/kakao/2018_news/</link><pubDate>Sun, 24 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2018_news/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/17677"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;자카드 유사도&#10;&lt;ul&gt;&#10;&lt;li&gt;집합 A = { 1, 2, 3 }, 집합 B = { 2, 3, 4 }&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;A ∩ B&lt;/code&gt; = { 2, 3 }&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;A ∪ B&lt;/code&gt; = { 1, 2, 3, 4 }&lt;/li&gt;&#10;&lt;li&gt;J(A, B) = 2 / 4&lt;/li&gt;&#10;&lt;li&gt;자카드 유사도는 0.5이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;중복을 허용하는 다중집합에서의 자카드 유사도&#10;&lt;ul&gt;&#10;&lt;li&gt;집합 A = { 1, 1, 2, 2, 3 }, 집합 B = { 1, 2, 2, 4, 5 }&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;A ∩ B&lt;/code&gt; = { 1, 2, 2 }&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;A ∪ B&lt;/code&gt; = { 1, 1, 2, 2, 3, 4, 5 }&lt;/li&gt;&#10;&lt;li&gt;J(A, B) = 3 / 7&lt;/li&gt;&#10;&lt;li&gt;자카드 유사도는 약 0.42이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;자카드 유사도를 문자열 사이에 적용&#10;&lt;ul&gt;&#10;&lt;li&gt;두 글자씩 끊어서 다중집합을 만든다.&lt;/li&gt;&#10;&lt;li&gt;FRANCE -&amp;gt; { FR, RA, AN, NC, CE }, FRENCH -&amp;gt; { FR, RE, EN, NC, CH }&lt;/li&gt;&#10;&lt;li&gt;교집합 = { FR, NC }&lt;/li&gt;&#10;&lt;li&gt;합집합 = { FR, NC, RA, AN, CE, RE, EN, CH }&lt;/li&gt;&#10;&lt;li&gt;J(FRANCE, FRENCH) = 2 / 8&lt;/li&gt;&#10;&lt;li&gt;자카드 유사도는 0.25이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;비교에 있어서 대문자와 소문자의 차이는 무시한다.&lt;/li&gt;&#10;&lt;li&gt;다중집합을 만듦에 있어서 두 문자가 영문자일 경우에만 집합에 포함한다.&#10;&lt;ul&gt;&#10;&lt;li&gt;&amp;ldquo;ab+&amp;ldquo;문자가 있으면 &amp;ldquo;ab&amp;quot;는 포함하고 &amp;ldquo;b+&amp;ldquo;는 포함하지 않는다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;유사도는 0에서 1사이의 실수이므로 65536을 곱한 후에 소수점 아래를 버린다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 풀이&lt;/p&gt;</description></item><item><title>[2018] 프렌즈 4 블록</title><link>https://lameld.github.io/kakao/2018_friendsblock/</link><pubDate>Thu, 21 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2018_friendsblock/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/17679"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙어있을 경우 사라지면서 점수를 얻는 게임이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/friend4block1.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>[DS] Queue</title><link>https://lameld.github.io/datastructure/dsqueue/</link><pubDate>Fri, 15 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/datastructure/dsqueue/</guid><description>&lt;h1 id="queue큐"&gt;Queue(큐)&lt;/h1&gt;&#10;&lt;h3 id="1-개념"&gt;1. 개념&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Queue는 FIFO(First In First Out)의 원리로 동작하는 자료구조이다.&lt;/li&gt;&#10;&lt;li&gt;동일한 자료의 집합을 다룬다는 면에서 Stack과 비슷하지만 가장 먼저 들어간 자료가 가장 늦게 나온다는 점이 다르다.&lt;/li&gt;&#10;&lt;li&gt;넣은 순서대로 자료를 꺼내가므로 순서대로 처리해야 하는 자료를 임시작으로 저장하는 용도로 흔히 사용한다.&lt;/li&gt;&#10;&lt;li&gt;저장되는 자료의 타입이 동일하므로 배열 또는 연결리스트로 Queue를 구현할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/queue1.png" alt="IMAGE"&gt;&lt;/p&gt;</description></item><item><title>프로그래머스 Python 풀이 노트</title><link>https://lameld.github.io/algorithms/programmers-python/</link><pubDate>Thu, 02 Oct 2025 00:00:00 +0000</pubDate><guid>https://lameld.github.io/algorithms/programmers-python/</guid><description>&lt;p&gt;&lt;a href="https://github.com/LaMelD/algorithms/blob/master/notebooks/programmers.ipynb"&gt;algorithms/notebooks/programmers.ipynb&lt;/a&gt;에 정리한 프로그래머스 Python 풀이를 글로 옮겼다. 문제 제목을 누르면 프로그래머스 문제 페이지로 간다. 뒤쪽에는 &lt;a href="https://github.com/LaMelD/algorithms/tree/master/python/programmers"&gt;python/programmers&lt;/a&gt;의 초기 스크립트 풀이 6개를 붙였다.&lt;/p&gt;</description></item><item><title>인덱스</title><link>https://lameld.github.io/mariadb/object-index/</link><pubDate>Wed, 19 Apr 2023 00:00:00 +0000</pubDate><guid>https://lameld.github.io/mariadb/object-index/</guid><description>&lt;h2 id="개념"&gt;개념&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;인덱스란?&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;SQL의 조회 성능을 향상시키기 위해서 테이블과는 별도로 생성되는 오브젝트&lt;/p&gt;</description></item><item><title>5장 시스템 관리 쉘 스크립트</title><link>https://lameld.github.io/shell/ch05/</link><pubDate>Fri, 24 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/shell/ch05/</guid><description>&lt;h3 id="51-디스크-사용량-분석보고"&gt;5.1 디스크 사용량 분석/보고&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.1.1 쉘 스크립트 코드&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 점검 용량 MB 단위 설정&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SETSIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;EXMB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;expr &lt;span class="nv"&gt;$SETSIZE&lt;/span&gt;&lt;span class="se"&gt;\*\(&lt;/span&gt;1024&lt;span class="se"&gt;\*&lt;/span&gt;1024&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# UID가 500 이상인 계정을 구분한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; name in &lt;span class="k"&gt;$(&lt;/span&gt;cut -d: -f1,3 /etc/passwd &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;$2 &amp;gt; 499 {print $1}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;사용자 &lt;/span&gt;&lt;span class="nv"&gt;$name의&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SETSIZE&lt;/span&gt;&lt;span class="s2"&gt; MB 초과 파일 목록 / 용량&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; find /user/tmp/home -user &lt;span class="nv"&gt;$name&lt;/span&gt; -type f -ls &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s2"&gt;&amp;#34;\$7 &amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$EXMB&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print &amp;#34;경로:&amp;#34; $11, &amp;#34;/ 용량:&amp;#34; $7}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;5.1.2 실행 결과&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./5-1.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;사용자 nobody의 10 MB 초과 파일 목록 / 용량&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;사용자 ubuntu의 10 MB 초과 파일 목록 / 용량&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;사용자 user01의 10 MB 초과 파일 목록 / 용량&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;사용자 user02의 10 MB 초과 파일 목록 / 용량&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;5.1.3 코드 분석&#10;&lt;ul&gt;&#10;&lt;li&gt;점검할 용량을 MB 단위로 설정하는 부분, 이후 점검 파일과 비교하기 위해 expr 명령어를 이용해 바이트 단위로 변환한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SETSIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;EXMB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;expr &lt;span class="nv"&gt;$SETSIZE&lt;/span&gt;&lt;span class="se"&gt;\*\(&lt;/span&gt;1024&lt;span class="se"&gt;\*&lt;/span&gt;1024&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;/etc/passwd 에서 UID가 500 이상인 계정을 대상으로 cut 명령어를 이용하여 첫 번째 필드와 세 번째 필드를 구분한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; name in &lt;span class="k"&gt;$(&lt;/span&gt;cut -d: -f1,3 /etc/passwd &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;$2 &amp;gt; 499 {print $1}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;name에 할당된 계정 소유자가 소유한 파일의 용량을 비교하여 설정된 용량보다 큰 파일의 경로와 세부 용량을 표시한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;사용자 &lt;/span&gt;&lt;span class="nv"&gt;$name의&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SETSIZE&lt;/span&gt;&lt;span class="s2"&gt; MB 초과 파일 목록 / 용량&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find /user/tmp/home -user &lt;span class="nv"&gt;$name&lt;/span&gt; -type f -ls &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s2"&gt;&amp;#34;\$7 &amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$EXMB&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print &amp;#34;경로:&amp;#34; $11, &amp;#34;/ 용량:&amp;#34; $7}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="52-사용자-계정-일시-정지"&gt;5.2 사용자 계정 일시 정지&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.2.1 쉘 스크립트 코드&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;stime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;90&lt;/span&gt; &#9;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ami&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;whoami&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ami&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;★본 프로그램은 체계관리자(ROOT)외 사용자는 실행이 제한됩니다. ★&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# $1 not exist&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;usage : 5-2.sh username&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;◆ &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;의 사용자 계정을 일시정지합니다. a ~ d 단계로 진행합니다.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; a &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; 계정의 패스워드를 변경해주세요&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;passwd &lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;tty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;who &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tail -1 &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="nv"&gt;$tty&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cat &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF &amp;gt; /dev/$tty&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;*************************************************************&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;★경 고 ★&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;지금 사용하고 있는 계정은 시스템관리자에게 의해 일시정지되니&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;90초 이후에는 강제 Log Out 됩니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;지금하는 작업을 마무리하시고 Log Out 바랍니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;계정사용 연장 및 기타문의사항은 시스템관리부서에 문의하세요&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ☎053-972-1234~8&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;*************************************************************&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sleep &lt;span class="nv"&gt;$stime&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;killall -s HUP -u &lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep &lt;span class="m"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;killall -s KILL -u &lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; b &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;의 사용중인 모든 프로세스는 종료되었습니다.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; c 현 시각부로 계정 &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; 은 Log Out 되었습니다. &amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; - &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; - &amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;000&lt;/span&gt; /home/&lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; d &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; 계정은 일시 정지 처리되었습니다.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;5.2.2 실행 결과&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./5-2.sh ubuntu&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;◆ ubuntu의 사용자 계정을 일시정지합니다. a ~ d 단계로 진행합니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;a ubuntu 계정의 패스워드를 변경해주세요&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter new UNIX password:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Retype new UNIX password:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;passwd: password updated successfully&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;b ubuntu의 사용중인 모든 프로세스는 종료되었습니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;c 현 시각부로 계정 ubuntu 은 Log Out 되었습니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Fri Jul 24 05:13:53 UTC 2020 -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d ubuntu 계정은 일시 정지 처리되었습니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;5.2.3 코드 분석&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 슬립 타임을 설정한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;stime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;90&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 현재 사용자를 알아온다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ami&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;whoami&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 계정 일시 정지는 root 사용자만 가능하도록 한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ami&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;★본 프로그램은 체계관리자(ROOT)외 사용자는 실행이 제한됩니다. ★&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 인자가 없으면 usage를 나타낸다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;usage : 5-2.sh username&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;◆ &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;의 사용자 계정을 일시정지합니다. a ~ d 단계로 진행합니다.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; a &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; 계정의 패스워드를 변경해주세요&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 비밀번호 변경을 위한 작업&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# user가 존재하지 않는 경우는 배제한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;passwd &lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 프롬프트는 1개 열려 있다는 가정에서 열려있는 프롬프트에 접근한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;tty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;who &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tail -1 &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="nv"&gt;$tty&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 열려있는 프롬프트가 없다면&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 열려있는 프롬프트가 있다면 알림을 보내준다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cat &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF &amp;gt; /dev/$tty&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;*************************************************************&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;★경 고 ★&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;지금 사용하고 있는 계정은 시스템관리자에게 의해 일시정지되니&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;90초 이후에는 강제 Log Out 됩니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;지금하는 작업을 마무리하시고 Log Out 바랍니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;계정사용 연장 및 기타문의사항은 시스템관리부서에 문의하세요&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; ☎053-972-1234~8&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;*************************************************************&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sleep &lt;span class="nv"&gt;$stime&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 프롬프트 프로세스를 종료시킨다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;killall -s HUP -u &lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sleep &lt;span class="m"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;killall -s KILL -u &lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; b &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;의 사용중인 모든 프로세스는 종료되었습니다.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; c 현 시각부로 계정 &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; 은 Log Out 되었습니다. &amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; - &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; - &amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# home path에 접근하지 못하도록 계정을 비활성화 한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod &lt;span class="m"&gt;000&lt;/span&gt; /home/&lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; d &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; 계정은 일시 정지 처리되었습니다.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="53-guest-및-공용-계정-초기화"&gt;5.3 guest 및 공용 계정 초기화&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.3.1 쉘 스크립트 코드&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;sampledir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/tmp/sample/&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ami&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;whoami&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ami&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;★본 프로그램은 체계관리자(ROOT)외 사용자는 실행이 제한됩니다. ★&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/passwd에서 user로 시작하는 계정을 추출한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; name in &lt;span class="k"&gt;$(&lt;/span&gt;cat /etc/passwd &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;/^user/{print $1}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;do&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /home/&lt;span class="nv"&gt;$name&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rm -r ./* &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cp -rp /&lt;span class="nv"&gt;$sampledir&lt;/span&gt; /home/&lt;span class="nv"&gt;$name&lt;/span&gt;/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; ■사용자 &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt; 의 홈디렉토리 초기화 완료&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;5.3.2 실행 결과&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./5-3.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;■사용자 B311148 의 홈디렉토리 초기화 완료&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;■사용자 B311146 의 홈디렉토리 초기화 완료&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;5.3.3 코드 분석&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 기본값으로 구성되어 있는 초기 상태의 user&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 없다면 새로 생성해야 한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;sampledir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/tmp/sample/&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 현재 사용자를 알기 위해&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ami&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;whoami&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# root 유저만 초기화할 수 있도록 설정한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ami&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;★본 프로그램은 체계관리자(ROOT)외 사용자는 실행이 제한됩니다. ★&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/passwd에서 B로 시작하는 계정을 추출한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; name in &lt;span class="k"&gt;$(&lt;/span&gt;cat /etc/passwd &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;/^B/{print $1}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;do&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /home/&lt;span class="nv"&gt;$name&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rm -r ./* &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cp -rp /&lt;span class="nv"&gt;$sampledir&lt;/span&gt; /home/&lt;span class="nv"&gt;$name&lt;/span&gt;/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; ■사용자 &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt; 의 홈디렉토리 초기화 완료&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="54-서버의-네트워크-상태-감시"&gt;5.4 서버의 네트워크 상태 감시&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.4.1 쉘 스크립트 코드&#10;&lt;ul&gt;&#10;&lt;li&gt;5-4.sh&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;serIP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/test/ch_5/serverIP.lst&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /test/ch_5/serverIP.lst에서 서버의 IP를 추출한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; ip in &lt;span class="k"&gt;$(&lt;/span&gt;cat &lt;span class="nv"&gt;$serIP&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;do&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;sername&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;grep &lt;span class="nv"&gt;$ip&lt;/span&gt; &lt;span class="nv"&gt;$serIP&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; ! ping -c &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="nv"&gt;$ip&lt;/span&gt; &amp;gt;&amp;gt; /dev/null &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;then&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; ★ &lt;/span&gt;&lt;span class="nv"&gt;$sername&lt;/span&gt;&lt;span class="s2"&gt; 서버 또는 네트워크 접속 제한 : 점검요망 ★&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; grep &lt;span class="nv"&gt;$sername&lt;/span&gt; &lt;span class="nv"&gt;$serIP&lt;/span&gt; &amp;gt;&amp;gt; /test/ch_5/Server_chk_err_&lt;span class="sb"&gt;`&lt;/span&gt;date +%C%y%m%d&lt;span class="sb"&gt;`&lt;/span&gt;.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;serverIP.lst&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WAS:192.168.3.128&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DB_1:192.168.3.129&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DB_2:192.168.3.120&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ftp:192.168.3.131&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mail:192.168.3.132&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;5.4.2 실행 결과&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./5-4.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;★ WAS 서버 또는 네트워크 접속 제한 : 점검요망 ★&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;★ DB_1 서버 또는 네트워크 접속 제한 : 점검요망 ★&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;★ DB_2 서버 또는 네트워크 접속 제한 : 점검요망 ★&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;★ ftp 서버 또는 네트워크 접속 제한 : 점검요망 ★&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;★ mail 서버 또는 네트워크 접속 제한 : 점검요망 ★&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;ping 점건 결과 이상이 있는 시스템을 화면에 표시하고, 점건이 필요한 서버를 Server_chk_err_날짜.log 파일에 저장한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;서버이름:서버IP&lt;/code&gt; 형식으로 log 파일에 저장된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;5.4.3 코드 분석&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 형식에 맞게 파일이 작성되어있어야 한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;serIP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/test/ch_5/serverIP.lst&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /test/ch_5/serverIP.lst에서 서버의 IP를 추출한다.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; ip in &lt;span class="k"&gt;$(&lt;/span&gt;cat &lt;span class="nv"&gt;$serIP&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;do&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;sername&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;grep &lt;span class="nv"&gt;$ip&lt;/span&gt; &lt;span class="nv"&gt;$serIP&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; ! ping -c &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="nv"&gt;$ip&lt;/span&gt; &amp;gt;&amp;gt; /dev/null &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;then&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; ★ &lt;/span&gt;&lt;span class="nv"&gt;$sername&lt;/span&gt;&lt;span class="s2"&gt; 서버 또는 네트워크 접속 제한 : 점검요망 ★&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; grep &lt;span class="nv"&gt;$sername&lt;/span&gt; &lt;span class="nv"&gt;$serIP&lt;/span&gt; &amp;gt;&amp;gt; /test/ch_5/Server_chk_err_&lt;span class="sb"&gt;`&lt;/span&gt;date +%C%y%m%d&lt;span class="sb"&gt;`&lt;/span&gt;.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="55-서비스-프로세스-상태-점검"&gt;5.5 서비스 프로세스 상태 점검&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.5.1 쉘 스크립트 코드 a&lt;/li&gt;&#10;&lt;li&gt;5.5.2 실행 결과 a&lt;/li&gt;&#10;&lt;li&gt;5.5.3 코드 분석 a&lt;/li&gt;&#10;&lt;li&gt;5.5.4 쉘 스크립트 코드 b&lt;/li&gt;&#10;&lt;li&gt;5.5.5 실행 결과 b&lt;/li&gt;&#10;&lt;li&gt;5.5.6 코드 분석 b&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="56-특정-디렉터리의-파일-내용-일괄-수정하기"&gt;5.6 특정 디렉터리의 파일 내용 일괄 수정하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.6.1 쉘 스크립트 코드&lt;/li&gt;&#10;&lt;li&gt;5.6.2 실행 결과&lt;/li&gt;&#10;&lt;li&gt;5.6.3 코드 분석&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="57-지정된-날짜의-웹-접속-통계"&gt;5.7 지정된 날짜의 웹 접속 통계&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.7.1 쉘 스크립트 코드&lt;/li&gt;&#10;&lt;li&gt;5.7.2 실행 결과&lt;/li&gt;&#10;&lt;li&gt;5.7.3 코드 분석&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="58-점검-결과를-메일로-보고"&gt;5.8 점검 결과를 메일로 보고&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.8.1 쉘 스크립트 코드&lt;/li&gt;&#10;&lt;li&gt;5.8.2 실행 결과&lt;/li&gt;&#10;&lt;li&gt;5.8.3 코드 분석&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="59-ftp를-이용한-파일-전송-자동화"&gt;5.9 ftp를 이용한 파일 전송 자동화&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.9.1 쉘 스크립트 코드&lt;/li&gt;&#10;&lt;li&gt;5.9.2 실행 결과&lt;/li&gt;&#10;&lt;li&gt;5.9.3 코드 분석&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="510-cron-스케줄-등록"&gt;5.10 cron 스케줄 등록&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.10.1 쉘 스크립트 코드&lt;/li&gt;&#10;&lt;li&gt;5.10.2 실행 결과&lt;/li&gt;&#10;&lt;li&gt;5.10.3 코드 분석&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="511-데몬-및-서비스-프로세스의-시작과-정지"&gt;5.11 데몬 및 서비스 프로세스의 시작과 정지&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.11.1 쉘 스크립트 코드&lt;/li&gt;&#10;&lt;li&gt;5.11.2 실행 결과&lt;/li&gt;&#10;&lt;li&gt;5.11.3 코드 분석&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="512-로그-파일-로테이션"&gt;5.12 로그 파일 로테이션&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;5.12.1 쉘 스크립트 코드 a&lt;/li&gt;&#10;&lt;li&gt;5.12.2 실행 결과 a&lt;/li&gt;&#10;&lt;li&gt;5.12.3 코드 분석 a&lt;/li&gt;&#10;&lt;li&gt;5.12.4 쉘 스크립트 코드 b&lt;/li&gt;&#10;&lt;li&gt;5.12.5 실행 결과 b&lt;/li&gt;&#10;&lt;li&gt;5.12.6 코드 분석 b&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>CH05. 쿠버네티스 입문</title><link>https://lameld.github.io/docker/ch-05/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-05/</guid><description>&lt;h2 id="1-쿠버네티스란-무엇인가"&gt;1. 쿠버네티스란 무엇인가?&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;INTRO&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 운영을 자동화하기 위한 컨테이너 오케스트레이션 도구( 구글의 주도로 개발되었다. )&lt;/li&gt;&#10;&lt;li&gt;컨테이너를 이용한 어플리케이션 배포할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;다양한 운영 관리 업무를 자동화할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;컨테이너 배치, 스케일링, 로드벨런싱, 헬스 체크 등 기능을 갖추고 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;도커의 부상과 쿠버네티스의 탄생&lt;/p&gt;</description></item><item><title>Linux</title><link>https://lameld.github.io/cloudbasic/linux/</link><pubDate>Thu, 16 Jan 2020 13:35:04 +0900</pubDate><guid>https://lameld.github.io/cloudbasic/linux/</guid><description>&lt;h3 id="200116-thursday--2001-sday"&gt;200116 Thursday ~ 2001?? ????sday&lt;/h3&gt;&#10;&lt;hr&gt;</description></item><item><title>4. 파이썬 날개 달기, 클래스</title><link>https://lameld.github.io/python/ch04/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/python/ch04/</guid><description>&lt;h3 id="1-파이썬-프로그래밍의-핵심-클래스"&gt;1. 파이썬 프로그래밍의 핵심, 클래스&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;한 클래스로 만들어진 두 인스턴스는 독립적인 개체이다.&lt;/p&gt;</description></item><item><title>4장 : 깃허브로 백업하기</title><link>https://lameld.github.io/gitstudy/ch4/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/gitstudy/ch4/</guid><description>&lt;h3 id="1-원격-저장소와-깃허브"&gt;1. 원격 저장소와 깃허브&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;원격 저장소&#10;&lt;ul&gt;&#10;&lt;li&gt;지역 저장소가 아닌 컴퓨터나 서버에 만든 저장소를 말한다.&lt;/li&gt;&#10;&lt;li&gt;지역 저장소와 연결되어 있으면서 &amp;lsquo;백업&amp;rsquo;과 &amp;lsquo;협업&amp;rsquo;이라는 중요한 역할을 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;깃허브로 할 수 있는 일&#10;&lt;ul&gt;&#10;&lt;li&gt;원격 저장소에서 깃을 사용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;지역 저장소를 백업할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;헙업 프로젝트에 사용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;자신의 개발 이력을 남길 수 있다.&lt;/li&gt;&#10;&lt;li&gt;다른 사람의 소스를 살펴볼 수 있고, 오픈 소스에 참여할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-깃허브-시작하기"&gt;2. 깃허브 시작하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://www.github.com"&gt;깃허브&lt;/a&gt;에 접속한 뒤 계정을 생성한다.&lt;/li&gt;&#10;&lt;li&gt;무료 계정과 유료 계정의 차이 : 협업할 수 있는 계정의 수가 제한되어 있다.&lt;/li&gt;&#10;&lt;li&gt;깃허브에 원격 저장소 만들기&#10;&lt;ul&gt;&#10;&lt;li&gt;repository를 새로 만들어 원격 저장소를 추가할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;Add a License : 오픈 소스 프로젝트를 위한 저장소를 만들 경우 해당 오픈 소스의 라이센스를 선택한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="3-지역-저장소를-원격-저장소와-연결하기"&gt;3. 지역 저장소를 원격 저장소와 연결하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;지역 저장소를 만든다.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git init [지역 저장소 이름]&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;지역 저장소와 원격 저장소를 연결한다.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git remote add [원격 저장소 이름] [원격 저장소 URL]&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;원격 저장소 이름 : 사용자 지정&lt;/li&gt;&#10;&lt;li&gt;github에서 지정되어 있는 URL :: &lt;code&gt;clone or download&lt;/code&gt;를 눌렀을 때 나오는 URL&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;지역 저장소와 원격 저장소의 연결 확인&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git remote -v&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="4-원격-저장소에-올리기-및-내려받기"&gt;4. 원격 저장소에 올리기 및 내려받기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;원격 저장소에 파일 올리기 :: &lt;code&gt;git push&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git push origin master&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;push : 원격 저장소에 올리겠다.&lt;/li&gt;&#10;&lt;li&gt;origin : 원격 저장소의 이름&lt;/li&gt;&#10;&lt;li&gt;master : 원격 저장소에 올릴 브랜치&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;원격 저장소에서 파일 받기 :: &lt;code&gt;git pull&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git pull origin master&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;pull : 원격 저장소에서 받아오겠다.&lt;/li&gt;&#10;&lt;li&gt;origin : 원격 저장소의 이름&lt;/li&gt;&#10;&lt;li&gt;master : 원격 저장소에 받아올 브랜치이름, 지역 저장소의 브랜치 이름&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="5-깃-허브에-ssh-원격-접속하기"&gt;5. 깃 허브에 SSH 원격 접속하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;생략하도록 하겠다&amp;hellip;&lt;/li&gt;&#10;&lt;li&gt;필요시 업데이트 하겠다&amp;hellip;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>5장 : 깃허브로 협업하기</title><link>https://lameld.github.io/gitstudy/ch5/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/gitstudy/ch5/</guid><description>&lt;h3 id="1-여러-컴퓨터에서-원격-저장소-함께-사용하기"&gt;1. 여러 컴퓨터에서 원격 저장소 함께 사용하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;원격 저장소 복제하기 :: &lt;code&gt;git clone&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git clone [복사할 원격 저장소의 URL]&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;위와 같이 사용하여 원격 저장소에서 복제할 수 있다.(복제한다 == 클론 == 클로닝)&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git clone [복제할 저장소의 URL] [복제할 디렉토리]&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;복제할 디렉토리가 없으면 새로 생성해준다.&lt;/li&gt;&#10;&lt;li&gt;복제할 디렉토리를 넣지 않으면 원격 저장소의 이름과 동일하게 복제된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;실습을 위한 두 환경 준비&#10;&lt;ul&gt;&#10;&lt;li&gt;두 환경을 만들어 각각 회사와 집이라고 생각하자.&lt;/li&gt;&#10;&lt;li&gt;git_home&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git clone [URL] git_home&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;git_office&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git clone [URL] git_office&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;개인 컴퓨터에서 작업하고 올리기&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd git_home&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim f1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;add c&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;회사 컴퓨터에서 내려받아 작업하기&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd ~/git_office&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git pull origin master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim f1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -am &amp;#34;add d&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;작업을 함에 있어서 항상 &lt;code&gt;git pull&lt;/code&gt;을 통해서 원격 저장소에 새로 올라온 커밋을 가져와야한다.&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-원격-브랜치-정보-가져오기"&gt;2. 원격 브랜치 정보 가져오기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;git pull&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;명령은 원격 저장소의 최신 커밋을 지역 저장소에 합쳐준다. 하지만 최신 커밋을 합치기 전에 원격 저장소에 어떤 변화가 있는지 먼저 살펴보아야 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;원격 브랜치 정보 가져오기 :: &lt;code&gt;git fetch&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;fetch(패치) : 불러오다, 가져오다&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;git fetch&lt;/code&gt; : 어떤 변화가 있는지 원격 저장소의 정보를 가져온다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd ~/git_office&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # 원격 저장소에서 변경을 실시한다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git fetch&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git log --oneline &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # 변화된 부분이 없다...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git status&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # git pull 명령을 사용하면 지역 저장소를 업데이트 할 수 있다고 한다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout FETCH_HEAD&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # 이제 변화된 부분을 확인할 수 있다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git merge FETCH_HEAD&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git log --oneline&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # 커밋 로그를 확인해보면 적용되어 있다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="3-협업의-기본-알아보기"&gt;3. 협업의 기본 알아보기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;공동 작업자 추가하기(팀장)&#10;&lt;ul&gt;&#10;&lt;li&gt;누구나 프로젝트의 소스를 내려받을 수 있지만 커밋을 푸시할 순 없다.&lt;/li&gt;&#10;&lt;li&gt;공동 작업자가 커밋을 푸시할 수 있도록 권하는 주는 것이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;작업 환경 구성하기(팀장, 팀원)&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init project&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd project&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # --global 옵션을 제거하여 현재 저장소에만 적용될 config입니다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config user.name &amp;#34;사용자 이름&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config user.email 사용자@이메.일&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;원격 저장소에 첫 커밋 푸시하기(팀장)&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim overview.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add overview.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;overview&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;새로운 깃허브 저장소를 만든다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote add origin [저장소 URL]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;공동 작업자 컴퓨터에서 원격 저장소 복제하기&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone [저장소 URL]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # 사용자 이름과 이메일을 설정한다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;첫 번재 커밋(팀장이 실시한)이 아니라면 풀 먼저하기&#10;&lt;ul&gt;&#10;&lt;li&gt;팀원이 작업트리에서 작업을 수행함에 있어서 팀장이 그 중에 푸시를 실시할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;팀원이 작업을 완료하고 푸시하려고 할 때 팀장의 새로운 커밋이 푸시되었으므로 rejected라는 오류 메시지가 나온다.&lt;/li&gt;&#10;&lt;li&gt;이를 방지하기위해서 푸하기전에 항상 풀을 먼저 실시해야 한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;같은 파일을 수정했을 경우 풀 과정에서 merge 에러가 발생할 수 있다.&lt;/strong&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;이럴경우 수동으로 이를 해결해주어야 한다&amp;hellip; 귀찮다&amp;hellip;&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="4-협업에서-브랜치-사용하기"&gt;4. 협업에서 브랜치 사용하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;협업을 하다 보면 팀원들이 각자 기능을 맡아서 작업하는 경우가 많다.&lt;/li&gt;&#10;&lt;li&gt;이럴 때는 각자의 작업이 master 브랜치에 있는 문서들과 섞이지 않도록 새 브랜치를 만들어서 버전을 관리한다.&lt;/li&gt;&#10;&lt;li&gt;각 팀원이 만든 새 브랜치 역시 원격 저장소에 그대로 푸시할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;새로 만든 브랜치 푸시하기&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git pull origin master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # checkout 명령에 -b 옵션을 붙여 브랜치를 새로 만들고 이동까지 한번에&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # f 브랜치가 있다면 브랜치로 이동&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout -b f&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ vim f1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add f1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add f1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;feature1&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin f&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;웹 브라우저로 원격 저장소로 접속하면 브랜치가 생성되어 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;풀 리퀘스트로 푸시한 브랜치 병합하기&#10;&lt;ol&gt;&#10;&lt;li&gt;브랜치 설명 옆에 있는 &lt;code&gt;New pull request&lt;/code&gt;를 누른다.&lt;/li&gt;&#10;&lt;li&gt;풀 리퀘스트 메시지를 작성한 후 &lt;code&gt;Create pull request&lt;/code&gt;를 누르면 협업 중인 저장소에 풀 리퀘스트가 전송된다.&lt;/li&gt;&#10;&lt;li&gt;협업 중인 원격 저장소에 등록된 풀 리퀘스트는 공동 작업자 중 누구나 살펴보고 병합할 수 있다. 저장소 파일 위의 &lt;code&gt;Pull request&lt;/code&gt;를 누르면 등록된 풀 리퀘스트 목록이 나타난다. 등록된 풀 리퀘스트를 누른다.&lt;/li&gt;&#10;&lt;li&gt;풀 리퀘스트 메시지를 살펴본 다음 내용에 문제가 없으면 &lt;code&gt;Merge pull request&lt;/code&gt;를 눌러 병합을 한다. 필요하다면 이 공간을 통해 풀 리퀘스트를 남간 사람과 메시지를 주고받을 수 있다.&lt;/li&gt;&#10;&lt;li&gt;커밋 메시지를 직접 입력하거나 기본 메시지를 사용할 수도 있다. &lt;code&gt;Confirm merge&lt;/code&gt;를 누르면 브랜치 병합이 끝난다.&lt;/li&gt;&#10;&lt;li&gt;브랜치가 병합되면 해당 브랜치에 있던 파일이 master 화면에 나타날 것이다. 브랜치 상태를 알고 싶다면 파일 목록 위에 있는 &lt;code&gt;2 branches&lt;/code&gt;를 눌러 보시오.&lt;/li&gt;&#10;&lt;li&gt;브랜치가 병합된 상태라면 &lt;code&gt;merged&lt;/code&gt;라고 표시되어 있다. 그리고 공동 작업자 중 누가 브랜치를 병합했는지도 알 수 있다.&lt;/li&gt;&#10;&lt;li&gt;깃허브에서 협업할 때는 보통 작업자마다 브랜치를 만들어서 진행하고, 작업 중간 중간 풀 리퀘스트를 보내서 master 브랜치에 병합한다. 그래서 깃허브로 협업할 때는 다른 작업자의 변경 내용을 바로 반영하기 위해서 항상 풀부터 한 다음 자신의 작업을 진행하는 것이 좋다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>[2018] 비밀지도</title><link>https://lameld.github.io/kakao/2018_secret/</link><pubDate>Sat, 23 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2018_secret/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/17681"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;문제 설명&#10;&lt;ol&gt;&#10;&lt;li&gt;지도는 한 변의 길이가 &lt;code&gt;n&lt;/code&gt; 인 정사각형 배열 형태로, 각 칸은 공백 또는 &amp;ldquo;#&amp;ldquo;으로 이루어져 있다.&lt;/li&gt;&#10;&lt;li&gt;전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 지도A, 지도B&lt;/li&gt;&#10;&lt;li&gt;두 지도는 각각 정수 배열로 암호화 되어 있다.&lt;/li&gt;&#10;&lt;li&gt;암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백부분을 0으로 부호화했을 때 얻어지는 이진수에 해당한는 값의 배열이다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/secret1.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>[DS] Stack</title><link>https://lameld.github.io/datastructure/dsstack/</link><pubDate>Fri, 15 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/datastructure/dsstack/</guid><description>&lt;h1 id="stack스택"&gt;Stack(스택)&lt;/h1&gt;&#10;&lt;h3 id="1-개념"&gt;1. 개념&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;가장 늦게 들어간 자료가 가장 먼저 나가는 구조이다.&lt;/li&gt;&#10;&lt;li&gt;후입선출(LIFO, Last In First Out)이라고도 부른다.&lt;/li&gt;&#10;&lt;li&gt;Stack에 데이터를 넣는 행동을 push, 데이터를 빼는 행동을 pop이라 한다.&lt;/li&gt;&#10;&lt;li&gt;Stack의 가장 위 데이터를 가르키는 포인터를 top이라고 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/stack1.png" alt="IMAGE"&gt;&lt;/p&gt;</description></item><item><title>CH06. 쿠버네티스 클러스터 구축</title><link>https://lameld.github.io/docker/ch-06/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-06/</guid><description>&lt;h2 id="1-google-kubernetes-engine-환경-설정"&gt;1. Google Kubernetes Engine 환경 설정&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;4장에서 구축한 TODO 어플리케이션을 쿠버네티스로 전환하고 GKE를 사용해서 배포할 것이다.&lt;/p&gt;</description></item><item><title>인프라 환경 변화의 시작, 클라우드</title><link>https://lameld.github.io/cloudbasic/cloud/</link><pubDate>Thu, 26 Mar 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/cloudbasic/cloud/</guid><description>&lt;hr&gt;&#10;&lt;h3 id="11-클라우드-컴퓨팅의-정의와-종류"&gt;1.1 클라우드 컴퓨팅의 정의와 종류&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;클라우드 컴퓨팅의 정의&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;클라우드 컴퓨팅은 인터넷이 가능한 디바이스로 제 3의 공간인 클라우드에서 데이터를 읽고 쓰고, 정보를 분석해 처리하며, 이를 저장하고 관리하는 컴퓨팅 시스템입니다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;클라우드 서비스의 종류&lt;/p&gt;</description></item><item><title>5. 파이썬 정규 표현식과 XML</title><link>https://lameld.github.io/python/ch05/</link><pubDate>Fri, 29 Nov 2019 17:38:30 +0900</pubDate><guid>https://lameld.github.io/python/ch05/</guid><description>&lt;h3 id="1-정규-표현식-살펴보기"&gt;1. 정규 표현식 살펴보기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;정규식의 필요성&#10;&lt;ul&gt;&#10;&lt;li&gt;장황한 parsing을 간편하고 직관적인 코드로 대체할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;park 800905-1049118&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;kim 700905-1059119&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;word_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isdigit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isdigit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;*******&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;word_result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word_result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;park 800905-1049118&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;kim 700905-1059119&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;(\d&lt;/span&gt;&lt;span class="si"&gt;{6}&lt;/span&gt;&lt;span class="s2"&gt;)[-]\d&lt;/span&gt;&lt;span class="si"&gt;{7}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;\g&amp;lt;1&amp;gt;-*******&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h3 id="2-정규-표현식-시작하기"&gt;2. 정규 표현식 시작하기&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;정규 표현식에서 사용하는 메타문자 : &lt;code&gt;. ^ $ * + ? { } [ ] \ | ( )&lt;/code&gt;&lt;/p&gt;</description></item><item><title>[2018] 셔틀버스</title><link>https://lameld.github.io/kakao/2018_shuttle/</link><pubDate>Fri, 22 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2018_shuttle/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/17678"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;셔틀은 &lt;code&gt;09:00&lt;/code&gt; 부터 총 &lt;code&gt;n&lt;/code&gt; 회 &lt;code&gt;t&lt;/code&gt; 분 간격으로 역에 도착하며, 하나의 셔틀에는 최대 &lt;code&gt;m&lt;/code&gt; 명의 승객이 탈 수 있다.&lt;/li&gt;&#10;&lt;li&gt;셔틀은 도착했을 때 도착한 순간 대기열에 선 크루까지 포함해서 대기 순서대로 태우고 바로 출발한다. 예를 들어 &lt;code&gt;09:00&lt;/code&gt; 에 도착한 셔틀은 자리가 있다면 &lt;code&gt;09:00&lt;/code&gt; 에 줄을 선 크루도 탈 수 있다.&lt;/li&gt;&#10;&lt;li&gt;콘(셔틀을 탈 승객)은 게으르기 때문에 같은 시각에 도착한 크루 중 대길에서 제일 뒤에 선다.&lt;/li&gt;&#10;&lt;li&gt;콘이 셔틀을 타고 사무실로 갈 수 있는 제일 늦은 시각을 출력한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;풀이&lt;/p&gt;</description></item><item><title>[C++ STL] Queue</title><link>https://lameld.github.io/datastructure/stlqueue/</link><pubDate>Sat, 16 Nov 2019 20:08:14 +0900</pubDate><guid>https://lameld.github.io/datastructure/stlqueue/</guid><description>&lt;h2 id="queue"&gt;Queue&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;내부적으로는 deque, list로 구성되어 있다.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;queue구조로 동작하도록 멤버 함수를 제공해준다.&lt;/p&gt;</description></item><item><title>CH07. 쿠버네티스 실전편</title><link>https://lameld.github.io/docker/ch-07/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-07/</guid><description>&lt;h2 id="1-쿠버네티스의-그-외-리소스"&gt;1. 쿠버네티스의 그 외 리소스&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;INTRO&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;쿠버네티스는 데몬으로 동작하는 서버 어플리케이션 외에도 배치 서버 등 다양한 형태의 어플리케이션을 구축할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;잡(Job)&lt;/p&gt;</description></item><item><title>오픈스택이란?</title><link>https://lameld.github.io/cloudbasic/openstack/</link><pubDate>Thu, 26 Mar 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/cloudbasic/openstack/</guid><description>&lt;hr&gt;&#10;&lt;h3 id="21-오픈스택의-역사"&gt;2.1 오픈스택의 역사&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;역사에 대한 내용은&amp;hellip;&lt;/li&gt;&#10;&lt;li&gt;Pass 하겠다&amp;hellip;&lt;/li&gt;&#10;&lt;li&gt;요청이 있다면 다루겠다&amp;hellip;&lt;/li&gt;&#10;&lt;li&gt;사실 구글링하면 다나옴&amp;hellip;&lt;/li&gt;&#10;&lt;li&gt;올리기 귀찮으니까&amp;hellip;&lt;/li&gt;&#10;&lt;li&gt;올리지 않겠음&amp;hellip;&lt;/li&gt;&#10;&lt;li&gt;추가된 새 기능은 블로그에 계속 업데이트 된다.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="http://naleejang.tistory.com/"&gt;필자의 블로그&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="22-오픈스택과-아키텍처"&gt;2.2 오픈스택과 아키텍처&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;오픈스택은 컴퓨트, 오브젝트 스토리지, 이미지, 인증 서비스 등이 유기적으로 연결되어 하나의 커다란 클라우드 컴퓨팅 시스템을 구축한다.&lt;/p&gt;</description></item><item><title>[2018] 추석 트래픽</title><link>https://lameld.github.io/kakao/2018_traffic/</link><pubDate>Sat, 23 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2018_traffic/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/17676"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;처리량의 변화가 어디서 일어나는지 알아내는 것에 어려움이 있었다. 큰 문제를 작은 문제로 나누어 풀어나간다는 것에 초점을 두고 하나의 로그데이터를 살펴보았을 때 어디서 처리량의 변화가 일어나는지 확인하였다. 이 과정에서 시간이 정말 오래걸렸다.&lt;/p&gt;</description></item><item><title>[C++ STL] Vector</title><link>https://lameld.github.io/datastructure/stlvector/</link><pubDate>Sat, 16 Nov 2019 20:08:14 +0900</pubDate><guid>https://lameld.github.io/datastructure/stlvector/</guid><description>&lt;h2 id="개념"&gt;개념&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;vector는 자동으로 메모리가 할당되는 배열이라고 생각하면 됩니다.&lt;/li&gt;&#10;&lt;li&gt;template를 사용하기 때문에 데이터 타입은 마음데로 넣을 수 있습니다.&lt;/li&gt;&#10;&lt;li&gt;Stack과 비슷한 구조를 가지고 있으며, 맨 뒤에서 삽입과 삭제가 가능합니다.&lt;/li&gt;&#10;&lt;li&gt;중간의 값을 삭제하거나 삽입이 가능하지만, 배열기반이므로 삽입과 삭제가 빈번하게 일어난다면 효율이 떨어집니다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="기본-생성법"&gt;기본 생성법&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;code&gt;&amp;lt;vector&amp;gt;&lt;/code&gt; 헤더파일을 추가해야한다.&lt;/p&gt;</description></item><item><title>CH08. 컨테이너 운영</title><link>https://lameld.github.io/docker/ch-08/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-08/</guid><description>&lt;h2 id="1-로깅-운영"&gt;1. 로깅 운영&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 환경의 효율적인 로그 관리 등 관리 운영적 부분에 중접을 두고 운영 환경에서 알아둬야 할 주의 사항을 설명한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;컨테이너에서 생성되는 로그&#10;&lt;ul&gt;&#10;&lt;li&gt;비컨테이너 환경&#10;&lt;ul&gt;&#10;&lt;li&gt;서버 업타임이 길기 때문에 로그가 누적되어 상당한 디스크 용량을 차지하는 일이 자주 발생한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;도커&#10;&lt;ul&gt;&#10;&lt;li&gt;로그 라이브러리를 사용해도 로그가 파일이 아니라 표준 출력으로 출력하고 이를 다시 Fluentd 같은 로그 컬렉터로 수집하는 경우가 많다.&lt;/li&gt;&#10;&lt;li&gt;어플리케이션 쪽에서 로그 로테이션을 할 필요가 없으며 로그 전송을 돕는 로깅 드라이버 기능도 갖추고 있으므로 로그 수집이 편리하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;표준 출력과 로그&#10;&lt;ul&gt;&#10;&lt;li&gt;gihyodocker/echo:latest 사용&lt;/li&gt;&#10;&lt;li&gt;포어그라운드로 실행한 다음 http://localhost:8080으로 요청을 보내면 표준 출력으로 출력된다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -it --rm -p 8080:8080 gihyodocker/echo:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2020/06/26 02:19:53 start server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2020/06/26 02:20:18 received request&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;호스트에 컨테이너 데이터가 저장되는 디렉터리 : /var/lib/docker/containers/컨테이너ID&lt;/li&gt;&#10;&lt;li&gt;컨테이너 데이터가 저장되는 디렉터리에 컨테이너ID-json.log 파일이 로그 파일이다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 컨테이너ID : 9b0eb43784afcc61efb36de58c4115931a0fa51fb87629ee6cff8624e0dd999a&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;컨테이너&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;컨테이너&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;또는&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 로그파일 있는 곳을 볼륨으로 컨테이너 생성&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt; &lt;span class="n"&gt;alpine&lt;/span&gt; &lt;span class="n"&gt;ash&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# cd json-log/[컨테이너ID]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;컨테이너&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# ls&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;컨테이너&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# tail [컨테이너ID]-json.log&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;컨테이너 표준 출력으로 출력된 내용이 JSON 포맷으로 출력된 것을 확인할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;어플리케이션에서 로그를 파일에 출력하도록 구현하지 않았더라도 도커에서 컨테이너의 표준 출력을 로그로 출력해 주는 것이다.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;로그 출력 자체를 완전히 도커에 맡길 수 있다.&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;로깅 드라이버&#10;&lt;ul&gt;&#10;&lt;li&gt;로그가 JSON 포맷으로 출력되는 이유는 도커에 json-file이라는 기본 로깅 드라이버가 있기 때문이다.&lt;/li&gt;&#10;&lt;li&gt;로깅 드라이버 : 도커 컨테이너가 출력하는 로그를 어떻게 다룰지를 제어하는 역할을 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;종류&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;설명&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Syslog&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;syslog로 로그를 관리&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Journald&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;systemd로 로그를 관리&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Awslogs&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;AWS CloudWatch Logs로 로그를 전송&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Gcplogs&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Google Cloud Logging으로 로그를 전송&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Fluentd&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;fluentd로 로그를 관리&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;컨테이너 로그 다루기&#10;&lt;ul&gt;&#10;&lt;li&gt;장애로 인해 예기치 않게 컨테이너가 정지되고 디스크에서 완전히 삭제되었다면 컨테이너 안에 로그를 파일로 남기면 컨테이너를 삭제할 때 로그도 함께 잃어버린다는 큰 문제가 발생한다.&lt;/li&gt;&#10;&lt;li&gt;방법&#10;&lt;ul&gt;&#10;&lt;li&gt;호스트에서 컨테이너에 공유한 볼륨에 파일로 로그를 남기는 방법&lt;/li&gt;&#10;&lt;li&gt;로그를 표준 출력으로 남기고 이 내용을 호스트에서 파일에 수집하는 방법&lt;/li&gt;&#10;&lt;li&gt;도커에서는 후자를 정석으로 여긴다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;컨테이너 로그의 로테이션&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 컨테이너 로깅 동작 제어 옵션 : &amp;ndash;log-opt&#10;&lt;ul&gt;&#10;&lt;li&gt;&amp;ndash;log-opt max-size=1m : 로테이션이 발생하는 로그 파일 최대 크기&lt;/li&gt;&#10;&lt;li&gt;&amp;ndash;log-opt max-file=5 : 최대 파일 개수. 이 값을 초과할 경우 오래된 파일부터 삭제된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -it --rm -p 8080:8080 --log-opt max-size=1m --log-opt max-file=5 gihyodocker/echo:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;max-size로 설정한 파일 크기에 도달하면 파일이 로테이션된다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----.log # 최신&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;----.log.1 # 이전 로그&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이 설정은 컨테이너마다 일일이 할 필요는 없고, 도커 데몬에서 log-opts 기본값으로 설정할 수 있다.&#10;&lt;ul&gt;&#10;&lt;li&gt;/etc/docker/daemon.json&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;log-driver&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;json-file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;log-opts&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max-size&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;10m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;max-file&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Fluentd와 Elasticsearch를 이용한 로그 수집 및 검색 기능 구축&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;파일 기반의 로그 관리 방식은 번거롭다.&lt;/p&gt;</description></item><item><title>[2019] 블록 게임</title><link>https://lameld.github.io/kakao/2019_block/</link><pubDate>Sun, 24 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2019_block/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/42894"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;아래와 같이 12가지 모양의 블록이 배치되어 있다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/block-game1.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>CH09. 가벼운 도커 이미지 만들기</title><link>https://lameld.github.io/docker/ch-09/</link><pubDate>Thu, 02 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-09/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;도커 이미지의 최적하 보다는 어플리케이션의 동작을 우선시했다.&lt;/li&gt;&#10;&lt;li&gt;일정 규모 이상의 어플리케이션을 본격적으로 구축하려면 도커 이미지 크기에도 신경 써야 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="1-가벼운-도커-이미지가-왜-필요할까"&gt;1. 가벼운 도커 이미지가 왜 필요할까&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;이미지 크기 증가에 따라 나타는 문제&#10;&lt;ul&gt;&#10;&lt;li&gt;이미지 크기가 미치는 영향&#10;&lt;ul&gt;&#10;&lt;li&gt;이미지 빌드 시간(기반 이미지 다운로드 시간 포함)&lt;/li&gt;&#10;&lt;li&gt;이미지를 도커 레지스트리에 등록하는 시간&lt;/li&gt;&#10;&lt;li&gt;컨테이너를 실행할 호스트 혹은 노드에서 이미지를 다운로드하는 시간&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;나비효과&#10;&lt;ul&gt;&#10;&lt;li&gt;클러스터를 구성하는 노드의 디스크 용량 낭비&lt;/li&gt;&#10;&lt;li&gt;CI 소요 시간 증가&lt;/li&gt;&#10;&lt;li&gt;개발 중 시행착오 소요 시간 증가로 인한 생산성 저하&lt;/li&gt;&#10;&lt;li&gt;오토 스케일리으로 컨테이너가 투입되는 소요 시간 증가(노드에 이미지가 없는 경우 새로 받아와야 하므로)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;새 노드에 얼마나 빨리 도커 이미지를 배치할 수 있는가가 중요하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="2-기반-이미지를-가볍게"&gt;2. 기반 이미지를 가볍게&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;scratch&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;빈 도커 이미지로, 도커가 이름을 예약한 특수 이미지다.&lt;/li&gt;&#10;&lt;li&gt;Dockerfile의 FROM 인스트럭션에서 참조만 가능하다.&lt;/li&gt;&#10;&lt;li&gt;컨테이너 외부로부터 파일을 주입받은 후에야 실체를 갖게 된다.&lt;/li&gt;&#10;&lt;li&gt;현재 존재하는 모든 도커 이미지의 기반 이미지를 따라가 보면 결국 이 scratch 이미지에 이르게 된다.&lt;/li&gt;&#10;&lt;li&gt;scratch 이미지는 모든 이미지의 조상 격이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;scratch 이미지로 만든 이미지 빌드 들여다보기&#10;&lt;ul&gt;&#10;&lt;li&gt;ubuntu:trusty 이미지의 Dockerfile&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;scratch&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ADD&lt;/span&gt; ubuntu-trusty-core-cloudimg-amd64-root.tar.gz /&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; -xe &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;#!/bin/sh&amp;#39;&lt;/span&gt; &amp;gt; /usr/sbin/policy-rc.d &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;exit 101&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /usr/sbin/policy-rc.d &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; chmod +x /usr/sbin/policy-rc.d &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; dpkg-divert --local --rename --add /sbin/initctl &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cp -a /usr/sbin/policy-rc.d /sbin/initctl &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sed -i &lt;span class="s1"&gt;&amp;#39;s/^exit.*/exit 0/&amp;#39;&lt;/span&gt; /sbin/initctl &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;force-unsafe-io&amp;#39;&lt;/span&gt; &amp;gt; /etc/dpkg/dpkg.cfg.d/docker-apt-speedup &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;DPkg::Post-Invoke { &amp;#34;rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true&amp;#34;; };&amp;#39;&lt;/span&gt; &amp;gt; /etc/apt/apt.conf.d/docker-clean &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;APT::Update::Post-Invoke { &amp;#34;rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial*.deb /var/cache/apt/*.bin || true&amp;#34;; };&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /etc/apt/apt.conf.d/docker-clean &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Dir::Cache::pkgcache &amp;#34;&amp;#34;; Dir::Cache::srcpkgcache &amp;#34;&amp;#34;;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; /etc/apt/apt.conf.d/docker-clean &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Acquire::Languages &amp;#34;none&amp;#34;;&amp;#39;&lt;/span&gt; &amp;gt; /etc/apt/apt.conf.d/docker-no-languages &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Acquire::GzipIndexes &amp;#34;true&amp;#34;; Acquire::CompressionTypes::Order:: &amp;#34;gz&amp;#34;;&amp;#39;&lt;/span&gt; &amp;gt; /etc/apt/apt.conf.d/docker-gzip-indexes &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Apt::AutoRemove::SuggestsImportant &amp;#34;false&amp;#34;;&amp;#39;&lt;/span&gt; &amp;gt; /etc/apt/apt.conf.d/docker-autoremove-suggests&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; rm -rf /var/lib/apt/lists/*&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; sed -i &lt;span class="s1"&gt;&amp;#39;s/^#\s*\(deb.*universe\)$/\1/g&amp;#39;&lt;/span&gt; /etc/apt/sources.list&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/bin/bash&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;ubuntu-trusty-core-cloudimg-amd64-root.tar.gz : 우분투 운영체제를 구성하는 최소한의 파일을 디렉토리 구조 그대로 압축한 것&lt;/li&gt;&#10;&lt;li&gt;ADD 인스트럭션은 COPY와 다르게 압축해제 기능이 있다.&lt;/li&gt;&#10;&lt;li&gt;CMD 인스트럭션에 /bin/bash 명령을 지정하여 컨테이너가 /bin/bash를 포어그라운드로 실행하므로 우분투 서버 자체가 상주 형태로 실행되는 것처럼 보인다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;어플리케이션을 실행하는데 운영 체제를 구성하는 파일을 모두 사용하는 것은 아니기 때문에 대부분의 파일은 쓸모없이 이미지의 용량만 차지한다.&lt;/li&gt;&#10;&lt;li&gt;간단한 이미지 만들기&#10;&lt;ul&gt;&#10;&lt;li&gt;hello.go 작성&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-golang" data-lang="golang"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hello, scratch!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;바이너리를 복사할 수 있도록 컨테이너 밖에서 컴파일한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ GOOS=linux GOARCH=amd64 go build hello.go&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;Dockerfile 작성&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;scratch&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; hello /&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 빌드&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build ch09/hello:latest .&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;컨테이너 실행&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -t ch09/hello:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 크기 확인&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image ls | grep hello&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;프로그래밍 언어로 된 어플리케이션은 언어 런타임이나 라이브러리 등을 이미지에 포함해야 하므로 Go 언어에 비해서 이미지가 커지는 경향이 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;네이티브 라이브러리 링크&#10;&lt;ul&gt;&#10;&lt;li&gt;C언어나 Go 언어에서 빌드한 실행 바이너리를 컨테이너에 복사하기만 하면 된다.&lt;/li&gt;&#10;&lt;li&gt;어플리케이션이 동적 링크를 사용하는 경우 주의해야 한다.&lt;/li&gt;&#10;&lt;li&gt;빌드시 네이티브 의존 라이브러리를 정적 링크하도록 하면 이미지를 만드는 수고를 크게 덜 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;루트 인증서&#10;&lt;ul&gt;&#10;&lt;li&gt;TLS/SSL이 적용된 웹 사이트에 접근&lt;/li&gt;&#10;&lt;li&gt;hello.go 수정&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-golang" data-lang="golang"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hello, scratch!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://gihyo.jp/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ioutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이 어플리케이션을 빌드하고 컨테이너로 실행하면 인증서 오류가 발생한다.&lt;/li&gt;&#10;&lt;li&gt;TLS/SSL이 적용된 HTTPS 웹 사이트에 접근하려면 루트 인증서가 필요하다.&lt;/li&gt;&#10;&lt;li&gt;일반적인 운영체제라면 루트 인증서가 포함되지만 scratch 이미지에는 루트 인증서 자체가 없기 때문에 오류가 발생한다.&lt;/li&gt;&#10;&lt;li&gt;Dockerfile 수정&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;scratch&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; hello /&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; cacert.pem /etc/ssl/certs/&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;운영 체제가 포함된 이미지라면 패키지 관리자를 통해 필요한 라이브러리나 도구를 추가할 수 있지만 scratch 이미지에는 패키지 관리자 같은 것이 존재하지 않는다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;scratch 이미지의 실용성&#10;&lt;ul&gt;&#10;&lt;li&gt;scratch 이미지에서 동작하려면 빌드부터 시작해야 하는 것은 물론, 다양한 의존 모듈이 필요하다.&lt;/li&gt;&#10;&lt;li&gt;디버그를 하려고 해도 셸이 없기 때문에 컨테이너 안의 상황을 파악하기가 어렵다.&lt;/li&gt;&#10;&lt;li&gt;이 점은 이미지의 크기와 트레이드 오프 관계를 가지므로 이러한 부분을 포기하더라도 작은 이미지가 필요한 상황이라면 scratch도 선택지에 포함시킬 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;busybox&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;busybox는 임베디드 시스템에서 많이 사용하는 리눅스 배포판이다.&lt;/li&gt;&#10;&lt;li&gt;busybox는 수백 종 이상의 기본 유틸리티를 갖추고 있다.&lt;/li&gt;&#10;&lt;li&gt;일반적인 운영 체제와 달리, 단일 바이너리 파일(/bin/busybox)에 모든 유틸리티가 포함된 형태다.&lt;/li&gt;&#10;&lt;li&gt;모든 명령어 파일이 /bin/busybox로 하드 링킹되어 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;표준 C 라이브러별 이미지&#10;&lt;ul&gt;&#10;&lt;li&gt;glibc&#10;&lt;ul&gt;&#10;&lt;li&gt;GNU C 라이브러리를 의미한다.&lt;/li&gt;&#10;&lt;li&gt;다양한 스펙 및 독자적인 확장 기능을 제공하기 때문에 유연하지만 그만큼 라이브러리 크기가 크다.&lt;/li&gt;&#10;&lt;li&gt;잘 사용하지 않는 기능 때문에 디스크 용량을 낭비한다는 문제가 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;uclibc&#10;&lt;ul&gt;&#10;&lt;li&gt;임베디드 환경에 특화된 가벼운 라이브러리로 추린 것이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;musl&#10;&lt;ul&gt;&#10;&lt;li&gt;musl은 정적 링크에 최적화되어 있어 어플리케이션을 이동에 유리한 단일 바이너리로 빌드하기에 좋다.&lt;/li&gt;&#10;&lt;li&gt;POSIX 표준을 더 충실히 구현한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;아키텍처나 운영 체제가 다른 환경에서 glibc로 빌드한 바이너리는 uClibc나 musl을 사용한 컨테이너에서 실행이 되지 않는다.&lt;/li&gt;&#10;&lt;li&gt;빌드 환경과 실행 환경의 차이를 배제하기 위해 -glibc, -uclibc, -musl과 같은 라이브러리별 이미지를 제공한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;busybox의 실용성&#10;&lt;ul&gt;&#10;&lt;li&gt;최소한의 운영 체제 기능을 제공하면서도 운영 체제로 인한 이미지 크기 증가는 거의 제로에 가깝게 줄여준다.&lt;/li&gt;&#10;&lt;li&gt;busybox를 포함한 이미지는 scratch로 만든 이미지보다 1MB 정도 크기가 크지만, 셸을 포함하고 있어 컨테이너 안에서 디버깅 작업이 가능하다.&lt;/li&gt;&#10;&lt;li&gt;에이전트 타입 어플리케이션이나 명령행 도구를 사용하는데 사용할 수 있다.(scratch와 마찬가지로)&lt;/li&gt;&#10;&lt;li&gt;패키지 관리자가 없다.&lt;/li&gt;&#10;&lt;li&gt;이미지 크기에 구애받지 않거나 이미지 빌드가 까다로운 경우에는 우분투나 CentOS 등의 이미지를 사용하는 것이 편리하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;alpine&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;busybox를 기반으로 한 리눅스 배포판으로 &amp;lsquo;보안, 간결함, 리소스 효율을 중시하는 파워 유저&amp;rsquo;를 대상으로 설계했으며, 표준 C 라이브러리 구현체 중 musl을 사용한다.&lt;/li&gt;&#10;&lt;li&gt;리눅스 배포판의 표준이라고 할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;패키지 관리자인 apk를 사용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;Dockerfile의 내용이 너무 장황하거나 이미지 빌드에 필요한 사전 준비가 지나치게 늘어나면 이미지 전체 내용을 파악하기 어려워진다. 이런 문제를 해결하려면 쓸 만한 패키지 관리자가 반드시 필요하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;alpine 컨테이너 실행하기&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run -it alpine:3.7 sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;패키지 관리자 apk 사용법&#10;&lt;ul&gt;&#10;&lt;li&gt;apk의 패키지 리포지토리가 중앙 집권적이라는 특징이 있다.&lt;/li&gt;&#10;&lt;li&gt;apk update : 로컬에 캐싱된 apk 패키지 인덱스를 업데이트하는 명령.&lt;/li&gt;&#10;&lt;li&gt;apk search : 현재 사용할 수 있는 패키지를 검색하는 명령.&lt;/li&gt;&#10;&lt;li&gt;apk add : 패키지를 설치하는 명령.&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;--no-cache&lt;/code&gt; 옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;/var/cache/apk 디렉터리에 저장된 apk 인덱스 대신 새로 받아온 인덱스 정보를 이용해 패키지를 설치한다.&lt;/li&gt;&#10;&lt;li&gt;/var/cache/apk 디렉터리에 캐시를 저장하지 않으므로 이 디렉터리의 내용을 따로 삭제할 필요도 없다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--virtual&lt;/code&gt; 옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;여러 패키지를 합쳐 하나의 별명을 붙이는 기능을 제공한다.&lt;/li&gt;&#10;&lt;li&gt;빌드 시에만 필요한 이미지를 그대로 남겨두면 이미지 크기가 불필요하게 증가할 수 있으므로 이 라이브러리를 제거하는 것이 좋다.&lt;/li&gt;&#10;&lt;li&gt;불필요한 패키지를 한번에 제거할 수 있다.(&lt;code&gt;apk del [별명]&lt;/code&gt;)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;apk del : 설치된 패키지를 제거하는 명령&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;알파인 리눅스 기반 도커 이미지 만들기&#10;&lt;ul&gt;&#10;&lt;li&gt;2장의 echo를 사용한다.&lt;/li&gt;&#10;&lt;li&gt;main.go&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;start server&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;received request&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello Docker!!!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;Dockerfile&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;alpine:3.7&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# (0) workspace 등록 및 환경 변수 등록&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WORKDIR /&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; GOPATH /go&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# (1) 빌드 시에만 필요한 라이브리 및 도구 설치&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk add --no-cache --virtual&lt;span class="o"&gt;=&lt;/span&gt;build-devs go git gcc g++&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# (2) 실행 시에도 필요한 라이브리 및 도구 설치&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk add --no-cache ca-certificates&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# (3) echo를 빌드해 실행 파일을 만듬&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . /go/src/github.com/lameld/echo&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /go/src/github.com/lameld/echo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go build -o bin/echo main.go&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /go/src/github.com/lameld/echo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cp bin/echo /usr/local/bin/&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# (4) 빌드 시에만 필요한 라이브러리 및 도구 제거&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk del --no-cache build-devs&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;echo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 빌드&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t ch09/echo:latest .&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="3-가벼운-도커-이미지-만들기"&gt;3. 가벼운 도커 이미지 만들기&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;배포 대상 어플리케이션 크기 줄이기&#10;&lt;ul&gt;&#10;&lt;li&gt;어플리케이션 크기 최적화&#10;&lt;ul&gt;&#10;&lt;li&gt;불필요한 파일 삭제&lt;/li&gt;&#10;&lt;li&gt;불필요한 프로그램 최소화&lt;/li&gt;&#10;&lt;li&gt;의존 라이브러리 최소화&lt;/li&gt;&#10;&lt;li&gt;웹 어플리케이션의 애셋(주로 이미지) 용량 줄이기&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;.dockerignore 파일&#10;&lt;ul&gt;&#10;&lt;li&gt;불필요한 파일 및 디렉터리가 컨텡너에 들어가지 않게 하는 것이 중요하다.&lt;/li&gt;&#10;&lt;li&gt;.git 디렉토리로 대표되는 불필요함 숨김 파일이 컨테이너에 들어가기 쉽다.&lt;/li&gt;&#10;&lt;li&gt;Dockerfile과 같은 디렉토리에에 위치차 .dockerignore 파일에 컨테이너 포함하지 않을 파일이나 디렉토리를 정의하는 기능이다.&lt;/li&gt;&#10;&lt;li&gt;.dockerignore&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.idea&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*.swp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.DS_STORE&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;도커 이미지의 레이어 구조 고려하기&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;이미지의 크기를 최적화하려면 이 내부 구조까지 깊이 이해할 필요가 있다.&lt;/li&gt;&#10;&lt;li&gt;echo 이미지를 빌드해 보면 다음과 같은 내용이 출력된다.&lt;/li&gt;&#10;&lt;li&gt;각 단계별로 Dockerfile에 기술된 명령이 실행되는 것을 알 수 있다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cmd" data-lang="cmd"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t ch09/echo:latest .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sending build context to Docker daemon 3.072kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 1/10 : FROM alpine:3.7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 6d1ef012b567&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 2/10 : WORKDIR /&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 96f74ddcf3b7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 3/10 : ENV GOPATH /go&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; acaeee72e27d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 4/10 : RUN apk add --no-cache --virtual=build-devs go git gcc g++&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; fa4f43acbc98&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 5/10 : RUN apk add --no-cache ca-certificates&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 1ad9964de84c&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 6/10 : COPY . /go/src/github.com/lameld/echo&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; f84186eefbc7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 7/10 : RUN cd /go/src/github.com/lameld/echo &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go build -o bin/echo main.go&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 77ffccfd40f7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 8/10 : RUN cd /go/src/github.com/lameld/echo &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cp bin/echo /usr/local/bin/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 56242e05b9ce&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 9/10 : RUN apk del --no-cache build-devs&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 9d06ac4d82e2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Step 10/10 : CMD [&lt;span class="s2"&gt;&amp;#34;echo&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Using cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 7bce58ed9dea&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully built 7bce58ed9dea&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully tagged ch09/echo:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;해당 이미지가 어떤 레이어로 구성되었는지 자세한 정보 보기 : &lt;code&gt;docker image history&lt;/code&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image history ch09/echo:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IMAGE CREATED CREATED BY SIZE COMMENT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7bce58ed9dea 2 minutes ago /bin/sh -c #(nop) CMD [&amp;#34;echo&amp;#34;] 0B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;9d06ac4d82e2 2 minutes ago /bin/sh -c apk del --no-cache build-devs 34kB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;56242e05b9ce 2 minutes ago /bin/sh -c cd /go/src/github.com/lameld/echo… 7.52MB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;77ffccfd40f7 2 minutes ago /bin/sh -c cd /go/src/github.com/lameld/echo… 7.52MB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;f84186eefbc7 2 minutes ago /bin/sh -c #(nop) COPY dir:afb826e60552ed0da… 713B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1ad9964de84c 2 minutes ago /bin/sh -c apk add --no-cache ca-certificates 515kB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fa4f43acbc98 2 minutes ago /bin/sh -c apk add --no-cache --virtual=buil… 359MB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acaeee72e27d 3 minutes ago /bin/sh -c #(nop) ENV GOPATH=/go 0B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;96f74ddcf3b7 3 minutes ago /bin/sh -c #(nop) WORKDIR / 0B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6d1ef012b567 16 months ago /bin/sh -c #(nop) CMD [&amp;#34;/bin/sh&amp;#34;] 0B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;missing&amp;gt; 16 months ago /bin/sh -c #(nop) ADD file:aa17928040e31624c… 4.21MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;각 레이어에 해당하는 이미지는 도커 파일 시스템 안에 tar.gz 파일에 저장된다.&lt;/li&gt;&#10;&lt;li&gt;레이어 자체도 이미지이며, 중간 과정에 특정한 태그를 붙일 수 있다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image tag f84186eefbc7 ch09/echo:copy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;레이어의 수를 최대한 줄이기&#10;&lt;ul&gt;&#10;&lt;li&gt;이미지를 구성하는 레이어 자체도 이미지 파일 형태로 디스크에 존재한다.&lt;/li&gt;&#10;&lt;li&gt;때문에 빌드 중에 필요했던 파일도 최종 결과물이 될 이미지에서 불필요한 파일이라면 결국 최종 이미지에 불필요한 파일에 들어간다.&lt;/li&gt;&#10;&lt;li&gt;entrykit 이미지&#10;&lt;ul&gt;&#10;&lt;li&gt;Dockerfile&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;alpine:3.7&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk add --no-cache wget&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; wget https://github.com/progrium/entrykit/releases/download/v0.4.0/entrykit_0.4.0_Linux_x86_64.tgz&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; tar -xvzf entrykit_0.4.0_Linux_x86_64.tgz&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; rm entrykit_0.4.0_Linux_x86_64.tgz&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; mv entrykit /bin/entrykit&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; chmod +x /bin/entrykit&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; entrykit --symlink&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 빌드&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;ch09&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;standard&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Sending&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;Docker&lt;/span&gt; &lt;span class="n"&gt;daemon&lt;/span&gt; &lt;span class="mf"&gt;2.048&lt;/span&gt;&lt;span class="n"&gt;kB&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;alpine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.7&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;d1ef012b567&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apk&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt; &lt;span class="n"&gt;wget&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;ddb2b2b256e&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;wget&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;progrium&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;releases&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit_0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="n"&gt;_Linux_x86_64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tgz&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bbb9cf07b1a2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;tar&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xvzf&lt;/span&gt; &lt;span class="n"&gt;entrykit_0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="n"&gt;_Linux_x86_64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tgz&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="n"&gt;ed24750e29&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="n"&gt;entrykit_0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="n"&gt;_Linux_x86_64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tgz&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;063&lt;/span&gt;&lt;span class="n"&gt;c338b89b0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;mv&lt;/span&gt; &lt;span class="n"&gt;entrykit&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="n"&gt;ae51cb1f1b&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;chmod&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dbfc1a91f15f&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;entrykit&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;symlink&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;5e6&lt;/span&gt;&lt;span class="n"&gt;c02d2e7c0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Successfully&lt;/span&gt; &lt;span class="n"&gt;built&lt;/span&gt; &lt;span class="mf"&gt;5e6&lt;/span&gt;&lt;span class="n"&gt;c02d2e7c0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Successfully&lt;/span&gt; &lt;span class="n"&gt;tagged&lt;/span&gt; &lt;span class="n"&gt;ch09&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;standard&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 레이어&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image history ch09/entrykit:standard&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IMAGE CREATED CREATED BY SIZE COMMENT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5e6c02d2e7c0 5 minutes ago /bin/sh -c entrykit --symlink 32B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dbfc1a91f15f 5 minutes ago /bin/sh -c chmod +x /bin/entrykit 9.19MB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;13ae51cb1f1b 5 minutes ago /bin/sh -c mv entrykit /bin/entrykit 9.19MB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;063c338b89b0 5 minutes ago /bin/sh -c rm entrykit_0.4.0_Linux_x86_64.tgz 0B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;72ed24750e29 5 minutes ago /bin/sh -c tar -xvzf entrykit_0.4.0_Linux_x8… 9.19MB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bbb9cf07b1a2 5 minutes ago /bin/sh -c wget https://github.com/progrium/… 2.71MB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;9ddb2b2b256e 6 minutes ago /bin/sh -c apk add --no-cache wget 480kB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6d1ef012b567 16 months ago /bin/sh -c #(nop) CMD [&amp;#34;/bin/sh&amp;#34;] 0B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;missing&amp;gt; 16 months ago /bin/sh -c #(nop) ADD file:aa17928040e31624c… 4.21MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;각 레이어에서 파일을 조작할 때마다 최종 이미지의 크기가 증가함을 알 수 있다.&lt;/li&gt;&#10;&lt;li&gt;이런 현상을 피하려면 Dockerfile을 빌드 해 생성되는 이미지의 레이어 수를 줄이는 것이 가장 효과적이다.&lt;/li&gt;&#10;&lt;li&gt;Dockerfile.light&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;alpine:3.7&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk add --no-cache wget &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://github.com/progrium/entrykit/releases/download/v0.4.0/entrykit_0.4.0_Linux_x86_64.tgz &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tar -xvzf entrykit_0.4.0_Linux_x86_64.tgz &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm entrykit_0.4.0_Linux_x86_64.tgz &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mv entrykit /bin/entrykit &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x /bin/entrykit &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;entrykit --symlink&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 빌드&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="n"&gt;built&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;Dockerfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;light&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;ch09&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;light&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Sending&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;Docker&lt;/span&gt; &lt;span class="n"&gt;daemon&lt;/span&gt; &lt;span class="mf"&gt;3.072&lt;/span&gt;&lt;span class="n"&gt;kB&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;alpine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.7&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;d1ef012b567&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;apk&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt; &lt;span class="n"&gt;wget&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;wget&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;progrium&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;releases&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit_0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="n"&gt;_Linux_x86_64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tgz&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;tar&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xvzf&lt;/span&gt; &lt;span class="n"&gt;entrykit_0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="n"&gt;_Linux_x86_64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tgz&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="n"&gt;entrykit_0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="n"&gt;_Linux_x86_64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tgz&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;mv&lt;/span&gt; &lt;span class="n"&gt;entrykit&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;chmod&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;entrykit&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;symlink&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b504a789d31f&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Successfully&lt;/span&gt; &lt;span class="n"&gt;built&lt;/span&gt; &lt;span class="n"&gt;b504a789d31f&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Successfully&lt;/span&gt; &lt;span class="n"&gt;tagged&lt;/span&gt; &lt;span class="n"&gt;ch09&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;entrykit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;light&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 레이어&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image history ch09/entrykit:light&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IMAGE CREATED CREATED BY SIZE COMMENT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;b504a789d31f About a minute ago /bin/sh -c apk add --no-cache wget &amp;amp;&amp;amp; wget h… 9.67MB &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6d1ef012b567 16 months ago /bin/sh -c #(nop) CMD [&amp;#34;/bin/sh&amp;#34;] 0B &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;missing&amp;gt; 16 months ago /bin/sh -c #(nop) ADD file:aa17928040e31624c… 4.21MB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;가독성과 이미지의 트레이드 오프&#10;&lt;ul&gt;&#10;&lt;li&gt;&amp;amp;&amp;amp;나 백슬래시를 만힝 사용해야 하며 빌드 스타일에 따라 cd 명령을 자주 사용하게 되므로 Dockerfile의 가독성을 해치게 된다.&lt;/li&gt;&#10;&lt;li&gt;이미지 빌드를 시행착오와 함께 반복해야 하는 경우라면 중간 빌드를 재활용하는 이점을 누릴 수가 없다.&lt;/li&gt;&#10;&lt;li&gt;이는 불가피하게 개발 효율을 떨어뜨리므로 개발 과정에서는 각 명령을 별도로 RUN 인스트럭션으로 실행한다.&lt;/li&gt;&#10;&lt;li&gt;빌드 내용이 고정된 다음에 RUN 인스트럭션의 실행 횟수를 줄이면 된다.&lt;/li&gt;&#10;&lt;li&gt;무리하게 모든 경우에 적용하지 않는 것이 좋다.&lt;/li&gt;&#10;&lt;li&gt;이 방법이 유용한 경우는 수 MB 이상의 파일으 자주 다루는 과정이 빌드에 포함되는 경우다.&lt;/li&gt;&#10;&lt;li&gt;중간 레이어 개수 자체가 적은 경우에는 굳이 적용할 필요가 없다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="4-멀티-스테이지-빌드"&gt;4. 멀티 스테이지 빌드&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;빌드 부산물을 완전히 제가할 수 없다는 한계의 대책 : 멀티 스테이지 빌드&lt;/li&gt;&#10;&lt;li&gt;빌드 컨테이너와 실행 컨테이너의 분리&#10;&lt;ul&gt;&#10;&lt;li&gt;적용 전&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.13&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WORKDIR /&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; GOPATH /go&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . /go/src/github.com/gihyodocker/todoapi&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go get github.com/go-sql-driver/mysql&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go get gopkg.in/gorp.v1&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /go/src/github.com/gihyodocker/todoapi &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go build -o bin/todoapi cmd/main.go&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /go/src/github.com/gihyodocker/todoapi &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cp bin/todoapi /usr/local/bin/&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;todoapi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;적용 후&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WORKDIR /&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; GOPATH /go&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . /go/src/github.com/gihyodocker/todoapi&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go get github.com/go-sql-driver/mysql&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; go get gopkg.in/gorp.v1&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /go/src/github.com/gihyodocker/todoapi &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go build -o bin/todoapi cmd/main.go&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;apline:3.7&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;build /go/src/github.com/gihyodocker/todoapi &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cp bin/todoapi /usr/local/bin/&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;todoapi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;빌드 산출물을 다른 컨테이너로 복사할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;실행 컨테이너에 불필요한 파일을 전혀 포함하지 않고 가벼운 이미지를 만들 수 있다.&lt;/li&gt;&#10;&lt;li&gt;Dockerfile의 가독성을 유지하면서도 이미지의 크기를 억제할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;장점&#10;&lt;ul&gt;&#10;&lt;li&gt;이미지 크기 감소뿐만 아니라 이식성에도 도움을 준다.&lt;/li&gt;&#10;&lt;li&gt;하나의 Dockerfile 안에서 컨테이너 간에 파일을 주고 받기 때문에 도커 호스트와 상관 없이 항상 같은 최종 결과물을 얻을 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>[2019] 실패율</title><link>https://lameld.github.io/kakao/2019_fail/</link><pubDate>Sun, 24 Nov 2019 00:00:00 +0000</pubDate><guid>https://lameld.github.io/kakao/2019_fail/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/42889"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;실패율 = A / B&#10;&lt;ul&gt;&#10;&lt;li&gt;A : 스테이지에 도달했으나 클리어하지 못한 플레이어 수&lt;/li&gt;&#10;&lt;li&gt;B : 스테이지에 도달한 플레이어 수&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;B가 0인 경우 실패율은 0으로 정의한다.&lt;/li&gt;&#10;&lt;li&gt;실패율이 높은 스테이지부터 내림차순으로 정렬된 배열을 리턴한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 풀이&lt;/p&gt;</description></item><item><title>CH10. 다양한 도커 활용 방법</title><link>https://lameld.github.io/docker/ch-10/</link><pubDate>Fri, 03 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ch-10/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;팀 개발에서 개발환경을 통일&lt;/li&gt;&#10;&lt;li&gt;명령행 도구를 통한 도커 컨테이너 사용법&lt;/li&gt;&#10;&lt;li&gt;도커를 이용한 부하 테스트 방법&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="1-팀-개발에서-개발-환경-통일하기"&gt;1. 팀 개발에서 개발 환경 통일하기&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;어플리케이션 및 미들웨어의 동작을 환경 변수로 제어하는 방법으로 도커 이미지의 추상 수준을 높일 수 있다.&lt;/li&gt;&#10;&lt;li&gt;다양한 환경에 배포하기 쉽게 할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;개발 환경을 공유하고 통일하는 방법으로 이용할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;소프트웨어 및 도구 통일&#10;&lt;ul&gt;&#10;&lt;li&gt;호스에서 격리된 환경에 필요한 도구를 갖춘 도커 컨테이너를 공통 개발 환경으로 사용하는 것이 바람직하다.&lt;/li&gt;&#10;&lt;li&gt;예시&#10;&lt;ul&gt;&#10;&lt;li&gt;MySQL이나 Redis 같은 데이터스토어를 사용한는 프로젝트는 이 외 데이터스토어를 조작하기 위한 클라이언트 도구가 필요하다.&lt;/li&gt;&#10;&lt;li&gt;고성능 MySQL 클라이언트인 mycli 혹은 Redis 클라이언트인 redis-tools를 팀의 표준 도구로 지정하면 다음과 같은 도커 이미지를 공통 개발 환경으로 사용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;Dockerfile&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;ubuntu:16.04&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apt -y update&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apt -y install net-tools &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iproute2 &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;inetutils-ping &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tcpdump &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mycli &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;redis-tools&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 빌드 및 컨테이너 생성(docker)&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t ch10/workspace:latest .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -it --name workspace ch10/workspace:latest bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;쿠버네티스에서 workspace 생성&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl run -i --rm --tty workspace --image=ch10/workspace:latest --restart=Never -- bash -il&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&amp;lsquo;하나의 컨테이너에 하나의 관심사&amp;rsquo;라는 도커의 원칙에는 어긋나지만, 어플리케이션 배포 용도가 아니므로 괜찮다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;개발 환경은 집단지성의 결과&#10;&lt;ul&gt;&#10;&lt;li&gt;팀 내 표준 개발 환경을 도커 컨테이너 형태로 제공하는 것은 매우 의미 있는 일이다.&lt;/li&gt;&#10;&lt;li&gt;장점&#10;&lt;ul&gt;&#10;&lt;li&gt;일단 개발 환경을 공유하면 여러 개발자가 수고를 덜 수 있다.&lt;/li&gt;&#10;&lt;li&gt;각자가 가진 노하우를 공유하고 이렇게 형성한 집단지성을 업무에 활용이 가능하다.&lt;/li&gt;&#10;&lt;li&gt;환경 구성 절차를 Dockerfile 형태의 프로그램으로 작성할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;신속하게 컨테이너를 실행하고 폐기할 수 있기 때문에 개발 환경에 베스트 프랙티스를 지속해서 반영할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="2-도커-컨테이너에서-명령행-도구cli-사용하기"&gt;2. 도커 컨테이너에서 명령행 도구(CLI) 사용하기&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Dockerfile의 문법 검사를 도와주는 명령행 도구인 hadolint를 도커 컨테이너 형태로 실행한다.&#10;&lt;ul&gt;&#10;&lt;li&gt;Dockerfile&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FROM alpine&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RUN echo &amp;#34;docker!!&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;검사&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm -i hadolint/hadolint &amp;lt; Dockerfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/dev/stdin:1 DL3006 Always tag the version of an image explicitly&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 버전 생략의 경고인 DL3006이 발생했다.&lt;/li&gt;&#10;&lt;li&gt;hadolint와 같은 도구를 처음 사용하더라도 추가적인 수고는 들지 않는다.&lt;/li&gt;&#10;&lt;li&gt;-i 옵션 : Dockerfile을 리다이렉트로 전달하기 위해서 사용하였다.&lt;/li&gt;&#10;&lt;li&gt;-v 옵션이 자주 같이 사용된다.&lt;/li&gt;&#10;&lt;li&gt;명령행 도구도 호스트에 설치하지 않고 도커 컨테이너 형태로 사용할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;이미지에서 명령행 도구 버전 변경하기&#10;&lt;ul&gt;&#10;&lt;li&gt;명령행 도구를 사용할 때 중요함 점이 도구의 버전을 관리하는 것이다.&lt;/li&gt;&#10;&lt;li&gt;명령행 도구를 편리하게 사용하려면도구 버전을 업데이트하거나 특정 버전으로 고정하는 작업이 꼭 필요하다.&lt;/li&gt;&#10;&lt;li&gt;명령행 도구를 사용하면서 다음과 같은 필요가 발생할 수 있다.&#10;&lt;ul&gt;&#10;&lt;li&gt;항상 최신 버전(보안 패치가 모두 적용된)을 사용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;버전이 바뀔 때마다 변경 사항이 많은 도구라서 특정 버전을 고정적으로 사용하고 싶다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;명령해 도구의 도커 이미지를 버전 별로 만들어 두는 것이 좋다.&#10;&lt;ul&gt;&#10;&lt;li&gt;언제든지 필요한 버전의 명령행 도구를 사용할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;예제 : jq를 도커 컨테이너로 실행&#10;&lt;ul&gt;&#10;&lt;li&gt;Dockerfile&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;alpine:3.7&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk add --no-cache --virtual&lt;span class="o"&gt;=&lt;/span&gt;build-devs wget &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mv jq-linux64 /usr/local/bin/jq &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x /usr/local/bin/jq &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apk del build-devs&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/usr/local/bin/jq&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-C&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;이미지 빌드 및 태그 변경&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t ch10/jq:latest .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image tag ch10/jq:latest ch10/jq:1.5&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;테스트&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ echo &amp;#39;{&amp;#34;version&amp;#34;:100}&amp;#39; | jq &amp;#39;.version&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ echo &amp;#39;{&amp;#34;version&amp;#34;:100}&amp;#39; | docker container run -i --rm ch10/jq:1.5 &amp;#39;.version&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;alias로 &lt;code&gt;docker container run -i --rm ch10/jq:1.5&lt;/code&gt;를 &lt;code&gt;jq1.5&lt;/code&gt;로 등록하여 사용할 수 있다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ alias jq1.5=&amp;#39;docker container run -i --rm ch10/jq:1.5&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ echo &amp;#39;{&amp;#34;version&amp;#34;:100}&amp;#39; | jq1.5 &amp;#39;.version&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;도커 컨테이너로 셸 스크립트 실행하기&#10;&lt;ul&gt;&#10;&lt;li&gt;배포 및 운영과 관련된 내용을 포함하는 셸 스크립트를 다양한 도구를 이용해 실행하는 경우도 많다.&lt;/li&gt;&#10;&lt;li&gt;여러 도구를 한꺼번에 다루거나 처리 과정을 코드로 옮겨 작업할 수 있다면 작업 효율이 향상시킬 수 있을 것이다.&lt;/li&gt;&#10;&lt;li&gt;스크립트가 자신이 의존하는 도구나 라이브러리의 버전을 업데이트하면서 또 다른 도구의 동작이 달라지는 경우도 있다.&lt;/li&gt;&#10;&lt;li&gt;셸 스크립트가 가볍고 편리하기는 하나 모든 환경에서 같은 동작을 보장하려면 여러모로 신경 써야 한다.&lt;/li&gt;&#10;&lt;li&gt;환경 차이에서 오는 불필요한 트러블을 방지하려면 스크립트와 스크립트가 의존하는 도구를 함께 도커 컨테이너에 격리해 놓으면 된다.&lt;/li&gt;&#10;&lt;li&gt;예제 : 표준 출력으로 출력된 JSON 문서에서 지정한 속성의 속성값을 추출한다.&#10;&lt;ul&gt;&#10;&lt;li&gt;show-attr.sh 작성(따로 실행 권한(+x)을 주지 않아도 된다.)&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ATTR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ATTR&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;required attribute name argument&amp;#34;&lt;/span&gt; 1&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;id&amp;#34;: 100,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;username&amp;#34;: &amp;#34;gihyo&amp;#34;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;comment&amp;#34;: &amp;#34;I like Alpine Linux&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq -r &lt;span class="s2"&gt;&amp;#34;.&lt;/span&gt;&lt;span class="nv"&gt;$ATTR&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;Dockerfile 작성&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;alpine:3.7&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk add --no-cache --virtual&lt;span class="o"&gt;=&lt;/span&gt;build-devs wget &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mv jq-linux64 /usr/local/bin/jq &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x /usr/local/bin/jq &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apk del build-devs&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; show-attr.sh /usr/local/bin/&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;sh&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/usr/local/bin/show-attr.sh&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;빌드 및 실행&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image build -t ch10/show-attr:latest .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container run --rm ch10/show-attr:latest username&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;마무리&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 이전의 셸 스크립트는 스크립트가 의존하는 도구나 라이브러리의 관리 문제와 스크립트만 봐서는 환경 구축 시에 알아야 할 내용을 파악하기 어렵다.&lt;/li&gt;&#10;&lt;li&gt;컨테이너를 이용해 스크립트와 그 실행 환경 자체를 분리하면 이식성 확보는 문론이고 Dockerfile 안에 스크립트가 의존하는 도구 및 라이브러리가 한눈에 정리된다.&lt;/li&gt;&#10;&lt;li&gt;CI/CD 단계에서 스크립트를 포함하는 컨테이너 자체를 테스트할 수도 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="3-부하-테스트"&gt;3. 부하 테스트&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;테스트 환경 구축&lt;/p&gt;</description></item><item><title>[2019] 후보키</title><link>https://lameld.github.io/kakao/2019_key/</link><pubDate>Sun, 24 Nov 2019 18:15:02 +0900</pubDate><guid>https://lameld.github.io/kakao/2019_key/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/42890"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;후보키 : 유일성과 최소성을 만족하는 것을 후보키(Candidate Key)라고 한다.&lt;/li&gt;&#10;&lt;li&gt;테이블이 주어졌을 때 후보키의 최대 갯수를 구한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;유일성(uniqueness)&lt;br&gt;&#10;릴레이션에 있는 모든 튜플에 대해 유일하게 식별되어야 한다.&lt;/p&gt;</description></item><item><title>부록 A : 보안</title><link>https://lameld.github.io/docker/ext-01-security/</link><pubDate>Tue, 14 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ext-01-security/</guid><description>&lt;h2 id="1-공개된-도커-이미지의-안전성"&gt;1. 공개된 도커 이미지의 안전성&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;공개적인 생태계의 특성상 악의적인 이미지가 포함될 가능성을 배제할 수 없다.&lt;/li&gt;&#10;&lt;li&gt;안전한 도커 이미지를 판단하는 기준을 파악하고 위험한 이미지를 가려내는 안목이 필요하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;도커 허브&#10;&lt;ul&gt;&#10;&lt;li&gt;도커의 기본적인 레지스트리이다.&lt;/li&gt;&#10;&lt;li&gt;docker search 명령으로 도커 허브에 등록된 이미지를 검색할 수 있다.&#10;&lt;ul&gt;&#10;&lt;li&gt;정렬&#10;&lt;ul&gt;&#10;&lt;li&gt;리포지토리의 스타 수(인기)&lt;/li&gt;&#10;&lt;li&gt;pull 횟수&lt;/li&gt;&#10;&lt;li&gt;OFFICIAL 항목 : &lt;code&gt;[OK]&lt;/code&gt;라면 도커 허브의 공식 리포지토리&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;OFFICIAL&#10;&lt;ul&gt;&#10;&lt;li&gt;해당 소프트웨어의 전문가나 보안 전문가와 협조해 이미지의 품질을 담보하기 위한 리뷰를 거친 것&lt;/li&gt;&#10;&lt;li&gt;일정 수준의 보안성을 확보했다고 할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Quay.io&#10;&lt;ul&gt;&#10;&lt;li&gt;CoreOS에서 운영하는 Quay.io&lt;/li&gt;&#10;&lt;li&gt;사설 리포지토리 및 자동 빌드(automated build)를 지원한다.&lt;/li&gt;&#10;&lt;li&gt;조직 관련 기능으로 팀 구성 및 롤 설정 기능을 제공하므로 도커 허브보다 훨씬 충실하게 팀 개발을 뒷바침할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;Quay.io는 취약점 정보 데이터베이스이 CVE 정보를 기초로 설치된 패키지를 통해 취약점 포함 여부를 확인한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Outro&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 허브에서 제공하는 공식 이미지나 Quay.io의 취약점 검사 등은 이미지의 안전성을 평가할 수 있는 중요한 지표이다.&lt;/li&gt;&#10;&lt;li&gt;이 지표가 완벽한 것은 아니다.&lt;/li&gt;&#10;&lt;li&gt;계획 중인 유즈케이스에 따라 어떤 위험이 따르는지 직접 확인하는 것이 중요하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="2-안전한-도커-이미지와-도커-운영-체제-꾸리기"&gt;2. 안전한 도커 이미지와 도커 운영 체제 꾸리기&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;각 개발자가 안전한 도커 이미지를 만들고 보안 위험이 발생하지 않도록 운영 체계를 구축할 필요가 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Docker Bench for Security&#10;&lt;ul&gt;&#10;&lt;li&gt;운영 환경에서 도커를 적용할 때 반드시 따라야 할 베스트 프랙티스의 준수 여부를 검사하는 도구&lt;/li&gt;&#10;&lt;li&gt;도커 컨테이너의 취약점을 발견하는 데 유용하다.&lt;/li&gt;&#10;&lt;li&gt;docker/docker-bench-security 이미지로 제공된다.&lt;/li&gt;&#10;&lt;li&gt;도커 호스트에서 실행&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;userns&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;audit_control&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;DOCKER_CONTENT_TRUST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;systemd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;systemd&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bench_security&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bench&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;security&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;실행 중인 컨테이너뿐만 아니라 도커 환경 전반에 걸친 취약점을 검사한다.&lt;/li&gt;&#10;&lt;li&gt;Docker daemon configuration : 도커 데몬의 설정을 검사&#10;&lt;ul&gt;&#10;&lt;li&gt;TLS/SSL이 적용되지 않은 비보안 레지스트리를 사용하고 있다면 &lt;code&gt;2.4 - Ensure insecure registries are not used&lt;/code&gt; 경고를 띄운다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Container Images and Build File : Dockerfile에 대한 검사&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 안에 어플리케이션 실행만을 위한 별도의 유저가 없다면 &lt;code&gt;4.1 - Ensure a user for the container has been created&lt;/code&gt; 경고를 띄운다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;운영 중 노출되기 쉬운 취약점을 탐지할 수 있으며 이 취약점을 해결하기 위한 베스트 프랙티스를 제시해 준다.&lt;/li&gt;&#10;&lt;li&gt;탐지된 취약점을 충분히 이해하는 것이 중요하다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;컨테이너에 파일을 추가하면서 발생하는 위험&#10;&lt;ul&gt;&#10;&lt;li&gt;Dockerfile로 컨테이너에 파일을 추가하는 인스트럭션 : ADD, COPY&#10;&lt;ul&gt;&#10;&lt;li&gt;COPY&#10;&lt;ul&gt;&#10;&lt;li&gt;호스트에서 파일이나 디렉터리를 복사해오는 기능을 수행&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;ADD&#10;&lt;ul&gt;&#10;&lt;li&gt;지정한 URL에서 파일을 내려받아 추가할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;압축 파일을 자동으로 해제하는 기능이 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;두 인스트럭션은 적절히 용도를 나눠 사용하지 않으면 취약점이 생길 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;URL에서 내려받은 파일이 항상 안전하다는 보장이 없다.&#10;&lt;ul&gt;&#10;&lt;li&gt;파일이 웹 사이트 소유자에 의해 변경될 수 있다.&lt;/li&gt;&#10;&lt;li&gt;악의를 품은 제삼자가 파일을 변조했을 수 있다.&lt;/li&gt;&#10;&lt;li&gt;이미지가 빌드될 때마다 결과물도 달라질 것이므로 항등성도 담보할 수 없다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;ADD 인스트럭션을 사용하려면 추가하려는 파일의 안전성을 먼저 검증해야 한다.&lt;/li&gt;&#10;&lt;li&gt;Dockerfile에는 ADD 인스트럭션 대신 COPY 인스트럭션을 사용하는 버릇을 들이는 것이 좋다.&lt;/li&gt;&#10;&lt;li&gt;RUN&#10;&lt;ul&gt;&#10;&lt;li&gt;wget이나 curl을 이용해 추가하는 방법도 있다.&lt;/li&gt;&#10;&lt;li&gt;호스트로부터 파일을 추가하는 게 아니라 파일 추가 과정 자체를 컨테이너 안으로 국한 시킬 수 있기 때문에 이식성이 뛰어나다.&lt;/li&gt;&#10;&lt;li&gt;ADD 인스트럭션과 마찬가지의 취약점을 가질 수 있다는 점을 이해하고 사용해야 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;예제 : 프로비저닝 도구 Terraform&#10;&lt;ul&gt;&#10;&lt;li&gt;Terraform은 실행 파일을 포함하는 zip 파일과 함께 SHA256으로 생성한 체크섬 정보를 제공한다.&lt;/li&gt;&#10;&lt;li&gt;적합성 검사 Dockerfile&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;alpine:3.7&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; &lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.11.5&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; apk --no-cache add --virtual&lt;span class="o"&gt;=&lt;/span&gt;build-devs curl gnupg&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# terraform과 배포 파일 체크섬 정보를 받음&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ADD&lt;/span&gt; https://releases.hashicorp.com/terraform/&lt;span class="nv"&gt;$VERSION&lt;/span&gt;/terraform_&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_linux__amd64.zip .&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ADD&lt;/span&gt; https://releases.hashicorp.com/terraform/&lt;span class="nv"&gt;$VERSION&lt;/span&gt;/terraform_&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_SHA256SUMS .&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ADD&lt;/span&gt; https://releases.hashicorp.com/terraform/&lt;span class="nv"&gt;$VERSION&lt;/span&gt;/terraform_&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_SHA256.sig .&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Keybase에 공개된 Hashicorp사의 PGP 공개키 임포트&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; curl https://keybase.io/hashicorp/pgp_keys.asc &lt;span class="p"&gt;|&lt;/span&gt; gpg --import&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 체크섬의 전자서명 검증&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; gpg --verify terraform_&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_SHA256SUMS.sig terraform_&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_SHA256SUMS&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 압축 파일의 체크섬 검증&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; cat terraform_&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_SHA256SUMS &lt;span class="p"&gt;|&lt;/span&gt; grep linux_amd64 &lt;span class="p"&gt;|&lt;/span&gt; sha256sum -cs&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; unzip terraform_&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_linux_amd64.zip&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; mv terraform /usr/local/bin/&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; terraform -v&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;Terraform을 개발한 Hashicorp는 Keybase에 PGP 공개키를 공개 중이다.&lt;/li&gt;&#10;&lt;li&gt;체크섬 정보의 서명을 검증한다.&lt;/li&gt;&#10;&lt;li&gt;서명이 확인되면 이 체크섬 정보를 zip 파일로부터 계산한 체크섬과 비교하는 방법으로 zip 파일의 정합성을 검증할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;체크섬 정보가 일치하지 않는다면 빌드는 실패 처리된다.&lt;/li&gt;&#10;&lt;li&gt;외부로 공개되는 Dockerfile에 이런 방식으로 검증 로직을 추가하면 이미지의 신뢰성을 향상시킬 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;적절한 접근 제어&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너를 침입으로부터 보호&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 중심의 개발 및 운영에서 가장 중요한 것은 외부인의 컨테이너 침입을 방지하는 것이다.&lt;/li&gt;&#10;&lt;li&gt;대책&#10;&lt;ul&gt;&#10;&lt;li&gt;root로 로그인 금지.&lt;/li&gt;&#10;&lt;li&gt;AWS의 보안 그룹, GCP의 방화벽을 적절히 설정하고 도커 호스트에 대한 접근 제어.&lt;/li&gt;&#10;&lt;li&gt;VPN 적용 및 내부망 접근 제한.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;/var/run/docker.sock의 컨테이너와의 공유 금지&#10;&lt;ul&gt;&#10;&lt;li&gt;도커는 유닉스 도메인 소켓 /var/run/docker.sock을 -v 옵션으로 마운트하고 이를 이용해 원격지의 도커 데몬에 접근한다.&lt;/li&gt;&#10;&lt;li&gt;이 소켓에 접근을 허용하면 컨테이너 생성 등의 작업을 원하는 대로 지시할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;/var/run/docker.sock을 사용하는 이미지의 사용은 원칙적으로 금해야 한다.&lt;/li&gt;&#10;&lt;li&gt;배포 중인 Dockerfile을 살펴보고 보호 대책을 마련해야 한다.&lt;/li&gt;&#10;&lt;li&gt;특별한 사정이 없다면 호스트의 /var/run/docker.sock을 컨테이너 마운트하는 일은 하지 않는 것이 좋다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;컨테이너 어플리케이션 실행용 사용자 추가&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 컨테이너 안에서 어플리케이션을 실행하는 기본 사용자 : root&lt;/li&gt;&#10;&lt;li&gt;도커 이미지를 빌드하는 과정이라면 root 권한을 갖는 쪽이 편하다. 하지만 이것이 보안에 큰 구멍이 될 수 있다.&lt;/li&gt;&#10;&lt;li&gt;도커는 호스트의 리소스를 컨테이너에서 공유하는 기술적 특징을 갖는다. 사용자 UID도 예외가 아니다.&lt;/li&gt;&#10;&lt;li&gt;모종의 경로를 통해 컨테이너에 침입했다면 사실상 호스트의 root 권한을 탈취한 것과 같다.&lt;/li&gt;&#10;&lt;li&gt;이런 문제를 방지하기 위해서 useradd 명령으로 어플리케이션 실행용 사용자를 생성하고 USER 인스트럭션에서 해당 사용자를 지정하면 된다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.9&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; mkdir /echo&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; main.go /echo/&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; useradd gihyo&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;gihyo&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;go&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;run&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/echo/main.go&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;컨테이너를 실행해 보면 gihyo 상용자가 어플리케이션을 실행하고 있음을 알 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;기밀정보 취급&#10;&lt;ul&gt;&#10;&lt;li&gt;환경 변수를 이용하는 방법&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너의 환경 변수 값은 너무 간단히 노출된다.&#10;&lt;ul&gt;&#10;&lt;li&gt;env 명령만 사용할 수 있다면 모든 환경 변수 값을 볼 수 있다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;docker container inspect &amp;lt;컨테이너 ID&amp;gt;&lt;/code&gt;명령도 같다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;환경 변수 방식을 적용하려면 권한 없는 제삼자가 도커 호스트나 도커 데몬을 조작할 수 없도록 적절한 접근 통제 정책을 먼저 실시해야 한다.&lt;/li&gt;&#10;&lt;li&gt;제삼자에게 기밀정보가 유출되어도 상관없도록 기밀정보 자체를 암호화하고 어플리케이션 안에서만 복호화할 수 있도록 구현하는 것도 좋은 방법이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;기밀정보를 외부에서 받아오는 방법&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 안에 있는 어플리케이션이 직접 외부에서 기밀정보를 받아오는 방법이 있다.&lt;/li&gt;&#10;&lt;li&gt;컨테이너에 접근하더라도 사용자는 아무런 기밀정보를 볼 수 없으며 어플리케이션이 원격지에 위치한 기밀정보를 참조해오는 방식이다.&lt;/li&gt;&#10;&lt;li&gt;이 기밀정보는 기계만 읽을 수 있는 형태이므로 기밀정보를 받아오는 통신 내용이 암호화되고 적절한 접근 통제만 되면 극히 안전한 방법이다.&lt;/li&gt;&#10;&lt;li&gt;예시&#10;&lt;ul&gt;&#10;&lt;li&gt;아마존 S3에 저장된 기밀정보에 접근하기 위해 IAM을 이용하는 방법이 있다.&lt;/li&gt;&#10;&lt;li&gt;Hashicorp가 개발한 Vault가 있다.&#10;&lt;ul&gt;&#10;&lt;li&gt;기밀정보를 저장하는 도구.&lt;/li&gt;&#10;&lt;li&gt;어플리케이션을 기밀정보를 전달받는 데이터베이스로 활용할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;암호화 기능, 기밀정보 열람 로그 기능, 무효화 기능 등을 제공한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>[2019] 매칭 점수</title><link>https://lameld.github.io/kakao/2019_matching/</link><pubDate>Sun, 24 Nov 2019 18:15:23 +0900</pubDate><guid>https://lameld.github.io/kakao/2019_matching/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/42893"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;한 웹페이지에 대해서 기본점수, 외부 링크 수, 링크점수, 매칭점수를 구할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;기본점수 : 텍스트 중에 검색어가 등장한 횟수(대소문자 무시)&lt;/li&gt;&#10;&lt;li&gt;외부 링크 수 : 다른 외부 페이지로 연결된 링크의 개수&lt;/li&gt;&#10;&lt;li&gt;링크점수 : ( 해당 웹페이지로 걸린 다른 웹페이지의 기본점수 ) / ( 외부링크 수) 의 합&lt;/li&gt;&#10;&lt;li&gt;매칭점수 : 기본점수 + 링크점수&lt;/li&gt;&#10;&lt;li&gt;매칭점수가 높은 웹페이지의 번호를 리턴한다.&lt;/li&gt;&#10;&lt;li&gt;매칭점수가 같은 웹페이지가 여러 개라면 그중 번호가 가장 작은 것을 구한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;입력 예시 : &lt;code&gt;[&amp;quot;&amp;lt;html lang=\&amp;quot;ko\&amp;quot; xml:lang=\&amp;quot;ko\&amp;quot; xmlns=\&amp;quot;http://www.w3.org/1999/xhtml\&amp;quot;&amp;gt;\n&amp;lt;head&amp;gt;\n &amp;lt;meta charset=\&amp;quot;utf-8\&amp;quot;&amp;gt;\n &amp;lt;meta property=\&amp;quot;og:url\&amp;quot; content=\&amp;quot;https://careers.kakao.com/interview/list\&amp;quot;/&amp;gt;\n&amp;lt;/head&amp;gt; \n&amp;lt;body&amp;gt;\n&amp;lt;a href=\&amp;quot;https://programmers.co.kr/learn/courses/4673\&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;#!MuziMuzi!)jayg07con&amp;amp;&amp;amp;\n\n&amp;lt;/body&amp;gt;\n&amp;lt;/html&amp;gt;&amp;quot;, &amp;quot;&amp;lt;html lang=\&amp;quot;ko\&amp;quot; xml:lang=\&amp;quot;ko\&amp;quot; xmlns=\&amp;quot;http://www.w3.org/1999/xhtml\&amp;quot;&amp;gt;\n&amp;lt;head&amp;gt;\n &amp;lt;meta charset=\&amp;quot;utf-8\&amp;quot;&amp;gt;\n &amp;lt;meta property=\&amp;quot;og:url\&amp;quot; content=\&amp;quot;https://www.kakaocorp.com\&amp;quot;/&amp;gt;\n&amp;lt;/head&amp;gt; \n&amp;lt;body&amp;gt;\ncon%\tmuzI92apeach&amp;amp;2&amp;lt;a href=\&amp;quot;https://hashcode.co.kr/tos\&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;\n\n\t^\n&amp;lt;/body&amp;gt;\n&amp;lt;/html&amp;gt;&amp;quot;]&lt;/code&gt;&lt;/p&gt;</description></item><item><title>부록 B : 도커로 개발을 지원하는 도구 및 서비스</title><link>https://lameld.github.io/docker/ext-02-tools/</link><pubDate>Fri, 10 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ext-02-tools/</guid><description>&lt;h2 id="1-인하우스-도커-레지스트리-구축"&gt;1. 인하우스 도커 레지스트리 구축&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 이미지를 보관하기에는 도커 허브나 Quay.io 같은 퍼블릭 레지스트리 서비스를 이용하는 것이 편리하다.&lt;/li&gt;&#10;&lt;li&gt;퍼블릭 레지스트리를 사용 불가한 경우&#10;&lt;ul&gt;&#10;&lt;li&gt;퍼블릭 레지스트리의 지나치게 긴 응답 시간&lt;/li&gt;&#10;&lt;li&gt;보안 측면의 문제&#10;&lt;ul&gt;&#10;&lt;li&gt;운영 환경에 배포하기 위해 개발한 어플리케이션 이미지를 퍼블릭 레지스트리에 저장할 수는 없다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;인하우스 도커 레지스트리&#10;&lt;ul&gt;&#10;&lt;li&gt;레지스트리를 직접 구축하여 어떤 보안 정책이라도 만족시킬 수 있다.&lt;/li&gt;&#10;&lt;li&gt;컨테이너를 배포하는 호스트와 가까이 도커 레지스트리가 위치할 것이므로 배포 속도 또한 개선할 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Registry(Docker Distribution)&#10;&lt;ul&gt;&#10;&lt;li&gt;도커에서 인하우스 도커 레지스트리를 구축할 수 있도록 배포하는 도구&lt;/li&gt;&#10;&lt;li&gt;Docker Distribution과 함께 제공된다.&lt;/li&gt;&#10;&lt;li&gt;오픈소스 소프트웨어이며 도커 컨테이너 형태로 실행할 수 있으므로 도커 호스트 역할을 할 운영 체제만 있으면 레지스트리 운영이 가능하다.&lt;/li&gt;&#10;&lt;li&gt;3장의 docker swarm을 구축할 때 사용했다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;구축&#10;&lt;ul&gt;&#10;&lt;li&gt;Registry 설치(서버) : ubuntu 16.x&#10;&lt;ul&gt;&#10;&lt;li&gt;/etc/systemd/system/docker-container@registry.service&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Unit]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Descriptioni=Registry&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Requires=docker.service&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;After=docker.service&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Service]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Restart=always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ExecStart=/usr/bin/docker container run --rm --name registry -p 5000:5000 library/registry&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Install]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WantedBy=multi-user.target&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;서비스로 활성화 한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ systemctl enable docker-container@registry.service&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ systemctl start docker-container@registry.service&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;곧 registry 컨테이너가 실행된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Registry에 이미지 등록하기&#10;&lt;ul&gt;&#10;&lt;li&gt;Registry는 HTTP API를 제공한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://localhost:5000/v2/_catalog&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;태그를 부여해 기존 알파인 리눅스 이미지를 Registry에 등록한다.&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image pull alpine:3.7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image tag alpine:3.7 localhost:5000/alpine:3.7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker image push localhost:5000/alpine:3.7&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Registry에서 이미지 내려받기&#10;&lt;ul&gt;&#10;&lt;li&gt;Registry 컨테이너를 실행한 호스트에서 localhost:5000으로 접근하면 된다.&lt;/li&gt;&#10;&lt;li&gt;그 외 호스트에서 Registry에서 접근하려면 도메인 부분을 다른 호스트에서 참조 가능한 IP 주소나 호스트명으로 바꿔야 한다.&lt;/li&gt;&#10;&lt;li&gt;docker image pull 명령은 기본적으로 HTTPS를 통해 레지스트리에 접근하기 때문에 Registry 역시 HTTPS를 활성화 하지 않으면 오류가 발생한다.&lt;/li&gt;&#10;&lt;li&gt;외부에서 접근이 불가능한 내부 네트워크 안에서만 이미지가 전송된다면 굳이 HTTPS를 적용할 필요가 없다.&#10;&lt;ul&gt;&#10;&lt;li&gt;docker image pull 명령을 실행하는 쪽의 /etc/docker/daemon.json 파일에 HTTP 통신을 허용한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Insecure registries&lt;/code&gt;에 값을 추가한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="2-도커와-cicd-서비스-연동"&gt;2. 도커와 CI/CD 서비스 연동&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;도커를 사용한 어플리케이션 개발 과정&#10;&lt;ul&gt;&#10;&lt;li&gt;구현 - 단위 테스트 - 어플리케이션 빌드 - 도커 이미지 빌드 - 도커 레지스트리 등록&lt;/li&gt;&#10;&lt;li&gt;위 과정의 반복&lt;/li&gt;&#10;&lt;li&gt;이 과정을 수작업으로 진행하면 실수가 발생하기 쉽다.&lt;/li&gt;&#10;&lt;li&gt;CI/CD 서비스에 이 과정을 맡기면 실수를 줄이고 시간도 적야할 수 있으므로 적절한 자동화 도입이 매우 중요하다.&#10;&lt;ul&gt;&#10;&lt;li&gt;CI : Continuous Integrate : 지속적 통합&lt;/li&gt;&#10;&lt;li&gt;CD : Continuous (Deploy | Delivery) : 지속적 배포&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;CI/CD 서비스의 예시 : Jenkins, CircleCI&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;CircleCI&#10;&lt;ul&gt;&#10;&lt;li&gt;INTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;SaaS(Software As A Service) 형태로 제공되는 CI/CD 서비스&lt;/li&gt;&#10;&lt;li&gt;빌드 설정 역시 yaml 포맷으로 기술할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;이번에 다루는 내용은 CircleCI와 github를 사용한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;github 계정으로 OAuth 인증을 거쳐 가입하고 로그인한다.&lt;/li&gt;&#10;&lt;li&gt;프로젝트 추가&#10;&lt;ul&gt;&#10;&lt;li&gt;github에 리포지토리를 새로 추가하고 내용으로 Dockerfile과 main.py를 생성한다.&#10;&lt;ul&gt;&#10;&lt;li&gt;Dockerfile&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Dockerfile" data-lang="Dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;python:3.6-alpine&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; main.py /app/main.py&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;python&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;main.py&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;main.py&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# simple-echo-server&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0.0.0.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;connected by&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sendall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hello python!!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;프로젝트가 추가되면 대상 저장소에 푸시가 일어날 때마다 웹훅이 CircleCI의 CI/CD 잡을 시작하게 한다.&lt;/li&gt;&#10;&lt;li&gt;깃허브 조직 저장소를 추가하려면 깃 허브 설정에서 CircleCI의 Organization access 권한을 부여해야 한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;빌드 설정 파일 작성&#10;&lt;ul&gt;&#10;&lt;li&gt;python 저장소를 이용해 도커 이미지 빌드에 이르는 과정을 설정한다.&lt;/li&gt;&#10;&lt;li&gt;.circleci/config.yml&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2.1&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# CircleCI 컨테이너의 작업 디렉토리&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;working_directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/app&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 잡을 실행하는 컨테이너의 도커 이미지&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;python:3.6-alpine&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;checkout &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 저장소에서 소스코드를 체크아웃&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;persist_to_workspace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# workspace를 후속 잡에서 사용할 수 있도록 유지&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;docker_build_push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;working_directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/app&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker:18.05.0-ce-dind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# docker 명령을 사용할 수 있는 컨테이너&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;attach_workspace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 저장해둔 workspace를 배치&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;setup_remote_docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# docker image build를 수행할 데몬 준비&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;18.05.0&lt;/span&gt;-&lt;span class="l"&gt;ce&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 도커 이미지 빌드&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker image build&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker image build -t joonstudydocker/echo-python:latest .&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 빌드된 이미지 확인&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker image ls&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker image ls&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 도커 허브 로그인&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker login&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker login -u $DOCKER_USER -p $DOCKER_PASS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 프로젝트 설정에서 환경 변수를 저장할 수 있다.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# latest 이미지를 도커 허브에 등록&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;release latest&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker image push joonstudydocker/echo-python:latest&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;workflows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build_and_push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# workflows로 실행할 잡을 열거&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;build&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;docker_build_push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# build 잡 다음에 실행&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;build&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# master 브랜치인 경우에만 실행&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 다른 브랜치에서도 실행하려면 주석 처리하거나 제거&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;master&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;CircleCI와 저장소를 연동하여 어플리케이션 테스트 및 도커 이미지 빌드와 등록을 대신해주는 CI/CD 환경을 구축하였다.&lt;/li&gt;&#10;&lt;li&gt;참고&#10;&lt;ul&gt;&#10;&lt;li&gt;docker login 오류 - ubuntu16.x&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo apt install gnupg2 pass &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gpg2 --full-generate-key&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gpg2 -k&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pass init &amp;#34;whatever key id you have&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="3-ecs에서-aws-fargate를-이용한-컨테이너-오케스트레이션"&gt;3. ECS에서 AWS Fargate를 이용한 컨테이너 오케스트레이션&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ECS - Elastic Container Service&#10;&lt;ul&gt;&#10;&lt;li&gt;AWS는 지금까지 독자적인 컨테이너 오케스트레이션 서비스 ECS를 제공해왔다.&lt;/li&gt;&#10;&lt;li&gt;ESC는 서버 여러대를 이용해 컨테이너 오케스트레이션을 구현하는 방식이다.&lt;/li&gt;&#10;&lt;li&gt;ALB라는 AWS 서비스와 매끄럽게 연동된다.&#10;&lt;ul&gt;&#10;&lt;li&gt;ALB - Application Load Balancer&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;ECS는 최초 도입이 쿠버네티스보다 쉽기 때문에 프로젝트 규모와 무관하게 널리 사용된다.&#10;&lt;ul&gt;&#10;&lt;li&gt;넷플릭스에서 대규모로 운영한 실적이 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;AWS Fargate&#10;&lt;ul&gt;&#10;&lt;li&gt;개발자가 서버나 클러스터를 직접 관리하지 않고 컨테이너를 실행하는 기술&lt;/li&gt;&#10;&lt;li&gt;ECS나 EKS에서는 서버관리, 클러스터 프로비저닝 등을 담당하는 서비스이다.&lt;/li&gt;&#10;&lt;li&gt;컨테이너 오케스트레이션부터 서버 및 클러스터 관리에 이르기까지 가장 손이 많이 가는 작업을 제거했다는 점에서 획기적이라 할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;AWS Fargate는 AWS Lambda의 뒤를 잇는 차세대 서버리스 기술로서도 주목받고 있다.&#10;&lt;ul&gt;&#10;&lt;li&gt;Lambda는 장시간 실행되는 배치 어플리케이션에는 적합하지 않은데, ECS는 이러한 약점을 보완할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;AWS Fargate는 서버 인스턴스를 신경 쓰지 않고도 간단히 컨테이너 오케스트레이션을 실현할 수 있으므로 컨테이너 기술 및 서버리스 기술 양쪽에서 새로운 트랜드가 될 것이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Fargate로 ECS 클러스터 구축&#10;&lt;ul&gt;&#10;&lt;li&gt;AWS console에서 ECS를 선택하면 Fargate 마법사 화면이 나타난다.&lt;/li&gt;&#10;&lt;li&gt;시작을 눌러서 설정을 시작한다.&lt;/li&gt;&#10;&lt;li&gt;1단계 : 컨테이너 및 작업&#10;&lt;ul&gt;&#10;&lt;li&gt;nginx를 선택한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;2단계 : 서비스&#10;&lt;ul&gt;&#10;&lt;li&gt;로드 밸런서 유형을 Application Load Balancer를 선택한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;3단계 : 클러스터&#10;&lt;ul&gt;&#10;&lt;li&gt;Cluster 이름을 설정한다.&lt;/li&gt;&#10;&lt;li&gt;필자는 joon으로 하겠다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;4단계 : 검토&#10;&lt;ul&gt;&#10;&lt;li&gt;지금까지의 내용을 검토한 뒤에 생성을 누른다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;생성 뒤 확인&#10;&lt;ul&gt;&#10;&lt;li&gt;ECS 관련 리소스가 수 분 만에 생성된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;생성된 nginx에 접속&#10;&lt;ul&gt;&#10;&lt;li&gt;생성한 뒤 로드 밸러서를 확인한다.&lt;/li&gt;&#10;&lt;li&gt;ECS 클러스터에 배포된 컨테이너는 모두 ALB라는 로드 밸런서를 통해 접근하므로 지금 만든 ALB의 DNS name을 복사한다.&lt;/li&gt;&#10;&lt;li&gt;웹 브라우저에서 &amp;lsquo;http://복사한도메인&amp;rsquo;에 접근하면 nginx의 welcome 화면을 볼 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;ECS를 조작해 어플리케이션 배포하기&#10;&lt;ul&gt;&#10;&lt;li&gt;ECS 리소스&#10;&lt;ul&gt;&#10;&lt;li&gt;(작음) Container Definition - Task Definition - Service - Cluster (큼)&lt;/li&gt;&#10;&lt;li&gt;Container Definition : 배포되는 각 컨테이너의 정의&lt;/li&gt;&#10;&lt;li&gt;Task Definition : 컨테이너의 집합인 Task의 정의&lt;/li&gt;&#10;&lt;li&gt;쿠버네티스 파드의 개념이 두 단계로 나뉘어 있다고 생각하면 된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Task Definition 생성&#10;&lt;ul&gt;&#10;&lt;li&gt;작업 정의 - 새로운 작업 정의 작성&lt;/li&gt;&#10;&lt;li&gt;FARGATE를 선택하고 다음을 누른다.&lt;/li&gt;&#10;&lt;li&gt;테스크 정의 이름은 echo-task로 한다.&lt;/li&gt;&#10;&lt;li&gt;네트워크 모드는 awsvpc를 선택하여 내부 IP(private)만 부여한다.&lt;/li&gt;&#10;&lt;li&gt;CPU 리소스&#10;&lt;ul&gt;&#10;&lt;li&gt;memory : 0.5GB&lt;/li&gt;&#10;&lt;li&gt;CPU : 0.25vCPU&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;컨테이너 정의&#10;&lt;ul&gt;&#10;&lt;li&gt;echo&#10;&lt;ul&gt;&#10;&lt;li&gt;이름 : echo&lt;/li&gt;&#10;&lt;li&gt;이미지 : stormcat24/echo:latest&lt;/li&gt;&#10;&lt;li&gt;포트 맵핑 : 8080&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;nginx&#10;&lt;ul&gt;&#10;&lt;li&gt;이름 : nginx&lt;/li&gt;&#10;&lt;li&gt;이미지 : stormcat24/nginx-proxy:latest&lt;/li&gt;&#10;&lt;li&gt;포트 맵핑 : 80&lt;/li&gt;&#10;&lt;li&gt;환경변수&#10;&lt;ul&gt;&#10;&lt;li&gt;BACKEND_HOST : value : localhost:8080&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;서비스 수정&#10;&lt;ul&gt;&#10;&lt;li&gt;새 배포 적용을 체크한다.&lt;/li&gt;&#10;&lt;li&gt;작업 개수는 1로 한다.&lt;/li&gt;&#10;&lt;li&gt;이후 화면은 수정 없이 다음을 클릭한다.&lt;/li&gt;&#10;&lt;li&gt;Service 수정이 끝나면 이미 배포된 태스크가 정지되며 echo-task:1 태스크가 하나 배포된다.&lt;/li&gt;&#10;&lt;li&gt;태스크 상세 정보를 확인하면 echo와 nginx 컨테이너를 포함한 태스크가 배포된 것을 알 수 있다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;ALB와 대상 그룹&#10;&lt;ul&gt;&#10;&lt;li&gt;Service는 ABL와 연동해 외부로부터 접근할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;RUNNING 상태가 된 태스크는 ALB가 확인한 헬스 체크 결과가 healthy로 나와야 비로소 트래픽이 전달된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;OUTRO&#10;&lt;ul&gt;&#10;&lt;li&gt;도커로 운영 환경을 꾸린다 해도 서버나 클러스터를 계속 신경써야 할 것이다.&lt;/li&gt;&#10;&lt;li&gt;그러나 Fargate를 사용하면 한 번 설정하면 그 이후에는 자동으로 제어된다.&lt;/li&gt;&#10;&lt;li&gt;이는 도커를 적용한 운영 환경을 쾌적하게 해주는 기술이다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>[2019] 무지의 먹방 라이브</title><link>https://lameld.github.io/kakao/2019_muzi/</link><pubDate>Sun, 24 Nov 2019 18:15:07 +0900</pubDate><guid>https://lameld.github.io/kakao/2019_muzi/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/42891"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;회전판에 먹어야 할 N개의 음식이 있다.&lt;/li&gt;&#10;&lt;li&gt;무지는 1번 음식부터 먹기 시작하며, 회전판은 번호가 증가하는 순서대로 음식을 무지 앞으로 가져다 놓는다.&lt;/li&gt;&#10;&lt;li&gt;무지는 음식 하나를 1초 동안 섭취한 후 남은 음식은 그대로 두고, 다음 음식을 섭취한다.&lt;/li&gt;&#10;&lt;li&gt;무지가 먹방을 시작한 지 K초 후에 네트워크 장애로 인해 방송이 잠시 중단되었다가 정상화 후 다시 방송을 이어갈 때, 몇 번 음식부터 섭취해야하는지 알고자 한다.&lt;/li&gt;&#10;&lt;li&gt;더 이상 섭취할 음식이 없다면 &lt;code&gt;-1&lt;/code&gt; 을 반환한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 풀이&lt;/p&gt;</description></item><item><title>부록 C : 주요 명령어 정리</title><link>https://lameld.github.io/docker/ext-03-command/</link><pubDate>Fri, 10 Jul 2020 00:00:00 +0000</pubDate><guid>https://lameld.github.io/docker/ext-03-command/</guid><description>&lt;h2 id="1-도커-명령어"&gt;1. 도커 명령어&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker image build [options] (Dockerfile경로 | URL)&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Dockerfile로부터 도커 이미지를 빌드&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker search [options] 키워드&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 허브에서 제공되는 도커 이미지를 검색&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker image pull [options] 리포지토리명[:태그명]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 레지스트리에서 도커 이미지를 다운로드&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker image ls [options] [리포지토리명[:태그명]]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;해당 도커 호스트가 보유한 도커 이미지의 목록을 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker image tag 이미지원래이름[:태그] 이미지새이름[:태그]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 이미지 태그를 생성&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker image push [options] 리포지토리명[:태그명]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 레지스트리에 도커 이미지를 전송해 등록&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container run [options] 이미지명[:태그명] [명령] [명령인자 ...]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;도커 컨테이너를 새로 실행&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container ls [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;dockerd가 보유한 컨테이너 목록 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container stop [options] (컨테이너ID | 컨테이너명)&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;실행중인 컨테이너를 정지&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container restart [options] (컨테이너ID | 컨테이너명)&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;정지한 컨테이너를 다시 실행&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container rm [options] (컨테이너ID | 컨테이너명)&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너를 디스크에서 삭제&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container logs [options] (컨테이너ID | 컨테이너명)&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너의 로그(표준 출력)를 화면에 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container exec -it [options] (컨테이너ID | 컨테이너명) 컨테이너에서_실행할_명령&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;실행 중인 컨테이너에서 명령어를 실행&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container cp [options] (컨테이너ID | 컨테이너명):원본파일 대상파일&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너에서 호스트로 파일 및 디렉토리 복사&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container cp [options] 호스트_원본파일 (컨테이너ID | 컨테이너명):대상파일&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;호스트에서 컨테이너로 파일 및 디렉토리 복사&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container prune [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;정지 상태인 모든 컨테이너를 디스크에서 삭제&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker image prune [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;사용하지 않는 모든 도커 이미지를 디스크에서 삭제&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker system prune [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;사용하지 않는 컨테이너 및 이미지, 볼륨, 네트워크 등 모든 도커 리소스를 일괄 삭제&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker container stats [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;시스템 리소스 사용 현황을 컨테이너 단위로 실시간 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="2-dockerfile-인스트럭션"&gt;2. Dockerfile 인스트럭션&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;FROM&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;빌드하는 이미지의 기반 이미지를 지정&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;RUN&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;이미지를 빌드할 때 컨테이너에서 실행할 명령어를 정의&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;COPY&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;호스트에서 컨테이너로 파일 및 디렉토리를 복사&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;ADD&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;COPY의 기능에 압축 파일 자동 해제 및 URL로부터 컨테이너에 파일 및 디렉토리 추가&lt;/li&gt;&#10;&lt;li&gt;운영 체제를 담은 기반 이미지를 만들 때처럼 특수한 경우에 활용&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;CMD&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너에서 포어그라운드로 실행할 명령어 정의&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;ENTRYPOINT&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너를 실행 가능 파일로 사용할 때 정의하는 명령&lt;/li&gt;&#10;&lt;li&gt;CMD와 ENTRYPOINT를 함께 사용할 수 있음&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;ARG&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;docker image build&lt;/code&gt;를 실행할 때 사용하는 변수&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;ENV&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 안의 환경 변수를 정의&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;EXPOSE&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너가 노출하는 포트&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;VOLUME&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;호스트나 다른 컨테이너에서 마운트할 수 있는 포인트 생성&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;LABEL&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;이미지에 추가하는 메타 데이터&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;STOPSIGNAL&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너에 전달되면 컨테이너를 종료하는 시스템 시그널 설정&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;HEALTHCHECK&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 안에서 명령을 실행하고 그 결과를 헬스 체크에 사용&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;USER&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 실행 시 컨테이너 사용자. 이미지 빌드 시 USER 정의 뒤에 나오는 RUN 인스트럭셔도 해당 사용자 권한으로 실행&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;WORKDIR&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너의 작업 디렉토리&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;ONBUILD&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컨테이너 안에서 실행되는 명령을 정의&lt;/li&gt;&#10;&lt;li&gt;이미지에서는 실행되지 않음&lt;/li&gt;&#10;&lt;li&gt;ONBUILD를 정의한 이미지를 기반 이미지로 삼아 다른 이미지를 빌드할 때 실행&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="3-도커-컴포즈-명령어"&gt;3. 도커 컴포즈 명령어&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose build [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 관리하는 서비스를 이미지로부터 빌드&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose create [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 관리하는 서비스를 생성&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose start [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 관리하는 서비스를 시작&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose up [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 관리하는 서비스를 생성 및 시작&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose stop [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 실행 중인 서비스를 정지&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose rm [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 실행 중인 서비스를 삭제&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose down [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 실행 중인 서비스를 정지 및 삭제&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose ps [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 실행 중인 컨테이너의 목록을 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker-compose logs [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;컴포즈로 실행 중인 컨테이너의 로그를 요약해 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="4-도커-스웜스택-명령어"&gt;4. 도커 스웜/스택 명령어&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker swarm init [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;스웜 클러스터를 초기화&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker swarm join [options] manager 호스트:포트&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;스웜 클러스터에 노드 혹은 매니저를 추가&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker swarm leave [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;스웜 클러스터에서 노드 혹은 매니저를 제거&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker stack deploy [options] 스택명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;스웜 클러스터에 스택을 배포&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker stack (ls | list) [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;스웜 클러스터에 배포된 스택 목록을 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker stack ps [options] 스택명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;스택 안에서 실행 중인 태스크를 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker stack (rm | remove | down) [options] 스택명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;스웜 클러스터에서 스택을 제거&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ docker stack services [options] 스택명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;스택에 포함된 서비스 목록을 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="5-헬름-명령어"&gt;5. 헬름 명령어&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm init [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;헬름을 초기화해 대상 쿠버네티스 클러스터를 배포할 수 있는 상태로 만든다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;--service-account&lt;/code&gt; : 틸러가 사용할 서비스 계정&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--node-selector&lt;/code&gt; : 틸러를 배포할 노드의 레이블&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--upgrade&lt;/code&gt; : 틸러 업그레이드&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--history-max&lt;/code&gt; : 리소스 하나당 유지할 히스토리 최대 수&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm version&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;헬름 명령행 도구와 틸러의 버전을 확인한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm create 차트명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;헬름 차트의 템플릿을 생성한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm lint 차트명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;생성된 차트 템플릿이나 Chart.yaml, values.yaml 파일이 문법에 어긋나지 않는지 검사한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm package [options] 차트_경로&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;차트를 압축 파일로 패키징한다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;--version&lt;/code&gt; : 차트의 버전&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;-d, --destination&lt;/code&gt; : 압축 파일을 출력할 디렉토리&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm repo list&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;헬름 명령행 도구로 사용할 수 있는 차트 리포지토리 목록을 출력한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm repo add 리포지토리명 리포지토리URL&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;차트 리포지토리를 추가한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm repo remove 리포지토리명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;현재 등록된 차트 리포지토리를 삭제한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm repo update&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;등록된 차트 리포지토리에서 최신 차트 정보를 받아온다.&lt;/li&gt;&#10;&lt;li&gt;반아온 정보는 로컬에 캐시되어 &lt;code&gt;helm search&lt;/code&gt; 명령 등에 사용된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm search [검색키워드] [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;등록된 차트 리포지토리에서 원하는 차트 정보를 검색한다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;-r, --regexp&lt;/code&gt; : 키워드에 정규 표현식을 사용&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;-l, --version&lt;/code&gt; : 리포지토리에 등록된 버전 목록을 출력&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm fetch [options] 차트URL | 차트 리포지토리나 차트명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;차트 리포지토리에서 패키지를 내려받는다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;--version&lt;/code&gt; : 내려받을 차트의 버전&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;사용 예시&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm fetch stable/redis&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm fetch stable/redis --version 3.6.0&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm serve [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;로컬 리포지토리로 사용할 웹 서버를 시작한다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;--address&lt;/code&gt; : 서버가 개방할 주소(기본값은 127.0.0.1)&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--repo-path&lt;/code&gt; : 차트 리포지토리가 될 로컬 디렉터리 경로&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm install 차트리포지토리/차트명 [optinos]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;차트를 이용해 어플리케이션을 설치한다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;--dry-run&lt;/code&gt; : 설치 시뮬레이션을 수행한다.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--name&lt;/code&gt; : 릴리즈명(미지정 시 자동 생성)&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;-f, --value&lt;/code&gt; : YAML 파일의 경로 또는 URL(여러 개 지정 가능)&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--version&lt;/code&gt; : 차트의 버전 지정&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm upgrade 릴리즈명 차트리포지토리명/차트명 [options]&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;기존에 설치된 릴리즈를 업데이트한다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;-f, --values&lt;/code&gt; : YAML 파일의 경로 혹은 URL(여러 개 지정 가능)&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--version&lt;/code&gt; : 차트의 버전&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--install&lt;/code&gt; : 릴리즈가 존재하지 않을 경우 새로 설치를 진행&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--reuse-values&lt;/code&gt; : 마지막 릴리즈의 값을 재사용하고 새로운 값을 merge&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm list&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;설치된 릴리즈의 목록을 확인한다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;--deleted&lt;/code&gt; : 삭제된 릴리즈를 목록에 포함&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--namespace&lt;/code&gt; : 지정한 네임스페이스의 릴리즈만을 확인&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm get [options] 릴리즈명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;설치된 릴리즈의 상세 정보를 YAML 포맷으로 출력한다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;--version&lt;/code&gt; : 릴리즈의 버전&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;$ helm delete [options] 릴리즈명&lt;/code&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;설치된 릴리즈를 삭제한다.&lt;/li&gt;&#10;&lt;li&gt;옵션&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;purge&lt;/code&gt; : 릴리즈를 삭제하고 릴리즈명을 해제한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>[2019] 오픈채팅방</title><link>https://lameld.github.io/kakao/2019_open/</link><pubDate>Sun, 24 Nov 2019 18:14:39 +0900</pubDate><guid>https://lameld.github.io/kakao/2019_open/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/42888"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;오픈채팅방에선 친구가 아닌 사람들과 대화가 가능하다.&lt;/li&gt;&#10;&lt;li&gt;채칭방에 들어오거나 나갈 때 메시지가 출력된다.&lt;/li&gt;&#10;&lt;li&gt;닉네임을 변경하는 방법은 2가지가 있다.&#10;&lt;ol&gt;&#10;&lt;li&gt;채팅방을 나간 후, 새로운 닉네임으로 다시 들어온다.&lt;/li&gt;&#10;&lt;li&gt;채팅방에서 닉네임을 변경한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;닉네임을 변경할 때는 기존에 채팅방에 출력되어 있던 메시지의 닉네임도 전부 변경된다.&lt;/li&gt;&#10;&lt;li&gt;채팅방은 중복 닉네임을 허용한다.&lt;/li&gt;&#10;&lt;li&gt;사용자는 유저아이디로 구분된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 풀이&lt;/p&gt;</description></item><item><title>[2019] 길 찾기 게임</title><link>https://lameld.github.io/kakao/2019_way/</link><pubDate>Sun, 24 Nov 2019 18:15:16 +0900</pubDate><guid>https://lameld.github.io/kakao/2019_way/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/42892"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;문제 설명&#10;&lt;ol&gt;&#10;&lt;li&gt;트리를 구성하는 모든 노드의 x, y 좌표 값은 정수이다.&lt;/li&gt;&#10;&lt;li&gt;모든 노드는 서로 다른 x값을 가진다.&lt;/li&gt;&#10;&lt;li&gt;같은 레벨에 있는 노드는 같은 y 좌표를 가진다.&lt;/li&gt;&#10;&lt;li&gt;자식 노드의 y값은 항상 부모 노드보다 작다.&lt;/li&gt;&#10;&lt;li&gt;임의의 노드 V의 왼쪽 서브 트리에 있는 모든 노드의 x값은 V의 x값보다 작다.&lt;/li&gt;&#10;&lt;li&gt;임의의 노드 V의 오른쪽 서브 트리에 있는 모든 노드의 x값은 V의 x값보다 크다.&lt;/li&gt;&#10;&lt;li&gt;노드들로 구성된 이진트리를 전위 준회, 후위 순회한 결과를 리턴한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/way1.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>[2020] 블록 이동하기</title><link>https://lameld.github.io/kakao/2020_block/</link><pubDate>Wed, 27 Nov 2019 11:22:43 +0900</pubDate><guid>https://lameld.github.io/kakao/2020_block/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/60063"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;문제 설명&#10;&lt;ul&gt;&#10;&lt;li&gt;아래의 왼쪽과 같이 board의 정보가 input으로 주어진다.&lt;/li&gt;&#10;&lt;li&gt;0과 1로 이루어진 N x N 크기의 지도에서 &lt;code&gt;2 x 1&lt;/code&gt; 크기의 로봇을 &lt;code&gt;(1, 1)&lt;/code&gt; 에서 &lt;code&gt;(N, N)&lt;/code&gt; 까지 이동시킨다.&lt;/li&gt;&#10;&lt;li&gt;시작은 아래의 왼쪽과 같이 시작한다.&lt;/li&gt;&#10;&lt;li&gt;로봇은 앞뒤 구분없이 움직일 수 있다.&lt;/li&gt;&#10;&lt;li&gt;로봇의 회전은 아래의 오른쪽과 같이 실행 할 수 있다.&lt;/li&gt;&#10;&lt;li&gt;로봇이 한칸 이동할 때 걸리는 시간은 1초이다.&lt;/li&gt;&#10;&lt;li&gt;90도 회전할 때 1초가 소요된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/moveblock1.jpg" alt=""&gt;&lt;/p&gt;</description></item><item><title>[2020] 외벽 점검</title><link>https://lameld.github.io/kakao/2020_circular/</link><pubDate>Wed, 27 Nov 2019 11:22:33 +0900</pubDate><guid>https://lameld.github.io/kakao/2020_circular/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/60062"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;외벽이 원형으로 이루어진 레스토랑의 외벽을 점검한다.&lt;/li&gt;&#10;&lt;li&gt;외벽의 총 둘레는 n미터이다.&lt;/li&gt;&#10;&lt;li&gt;최소한의 인원을 투입하여 취약 지점을 점검한다.&lt;/li&gt;&#10;&lt;li&gt;정북 방향 지점을 0으로 한다.&lt;/li&gt;&#10;&lt;li&gt;인원들 각각이 1시간 동안 이동할 수 있는 거리는 다르다.&lt;/li&gt;&#10;&lt;li&gt;최대로 투입 가능한 인원의 수는 8명이 한계이다.&lt;/li&gt;&#10;&lt;li&gt;취약점의 최대 갯수는 15곳이다.&lt;/li&gt;&#10;&lt;li&gt;모든 인원을 투입해도 취약점을 전부 점검할 수 없을 경우 -1을 리턴한다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;예시&lt;/p&gt;</description></item><item><title>[2020] 괄호 변환</title><link>https://lameld.github.io/kakao/2020_convert/</link><pubDate>Wed, 27 Nov 2019 11:21:17 +0900</pubDate><guid>https://lameld.github.io/kakao/2020_convert/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/60058"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;문제 설명&#10;&lt;ul&gt;&#10;&lt;li&gt;균형잡힌 괄호 문자열 : &amp;lsquo;(&amp;lsquo;의 개수와 &amp;lsquo;)&amp;lsquo;의 개수가 같다.&lt;/li&gt;&#10;&lt;li&gt;올바른 문자열 : &amp;lsquo;(&amp;lsquo;와 &amp;lsquo;)&amp;lsquo;의 괄호의 개수가 같고, 짝도 맞다.&lt;/li&gt;&#10;&lt;li&gt;해당 문제에서 제시된 설명은 다음과 같다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;입력이 빈 문자열인 경우, 빈 문자열을 반환합니다.&lt;/li&gt;&#10;&lt;li&gt;문자열 w를 두 &amp;ldquo;균형잡힌 괄호 문자열&amp;rdquo; u, v로 분리합니다. 단, u는 &amp;ldquo;균형잡힌 괄호 문자열&amp;quot;로 더 이상 분리할 수 없어야 하며, v는 빈 문자열이 될 수 있습니다.&lt;/li&gt;&#10;&lt;li&gt;문자열 u가 &amp;ldquo;올바른 괄호 문자열&amp;rdquo; 이라면 문자열 v에 대해 1단계부터 다시 수행합니다.&#10;&lt;ol&gt;&#10;&lt;li&gt;수행한 결과 문자열을 u에 이어 붙인 후 반환합니다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;문자열 u가 &amp;ldquo;올바른 괄호 문자열&amp;quot;이 아니라면 아래 과정을 수행합니다.&#10;&lt;ol&gt;&#10;&lt;li&gt;빈 문자열에 첫 번째 문자로 &amp;lsquo;(&amp;lsquo;를 붙입니다.&lt;/li&gt;&#10;&lt;li&gt;문자열 v에 대해 1단계부터 재귀적으로 수행한 결과 문자열을 이어 붙입니다.&lt;/li&gt;&#10;&lt;li&gt;&amp;lsquo;)&amp;lsquo;를 다시 붙입니다.&lt;/li&gt;&#10;&lt;li&gt;u의 첫 번째와 마지막 문자를 제거하고, 나머지 문자열의 괄호 방향을 뒤집어서 뒤에 붙입니다.&lt;/li&gt;&#10;&lt;li&gt;생성된 문자열을 반환합니다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;문제 풀이 : 문제에 제시되어 있는 설명을 참고하여 순차적으로 적용하면 된다.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//올바른 괄호인지 판별&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;is_right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;(&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//균형잡힌 문자열인지 판별&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;is_balanced&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;(&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//문자열 s를 균형잡힌 문자열 u, v로 나눈다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_balanced&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_balanced&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//u, v가 모두 균형잡힌 상태에서&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//u가 올바른 문자열이라면&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="c1"&gt;//ret에 u를 푸시하고 v를 검사한다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//u가 올바른 문자열이 아니라면&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="c1"&gt;//문제에 제시된 내용으로 해결한다&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;(&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;(&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//올바른 괄호라면 원형 문자열을 리턴&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//아니라면 괄호 변환을 실시하여 리턴한다.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>[2020] 자물쇠와 열쇠</title><link>https://lameld.github.io/kakao/2020_lock/</link><pubDate>Wed, 27 Nov 2019 11:21:28 +0900</pubDate><guid>https://lameld.github.io/kakao/2020_lock/</guid><description>&lt;h1&gt;카카오 블라인드 테스트 2020 - 자물쇠와 열쇠&lt;/h1&gt;&#10;&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/60059"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;문제 설명&#10;&lt;ol&gt;&#10;&lt;li&gt;자물쇠의 크기 : M * M&lt;/li&gt;&#10;&lt;li&gt;열쇠의 크기 : N * N&lt;/li&gt;&#10;&lt;li&gt;열쇠는 회전과 이동이 가능하며 열쇠의 돌기 부분을 자물쇠 홈 부분에 맞게 채우면 자물쇠가 열리는 구조이다.&lt;/li&gt;&#10;&lt;li&gt;열쇠를 자물쇠에 끼워 넣었을 때 빈 부분이 없어야 자물쇠를 열 수 있다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img src="https://lameld.github.io/images/lock1.jpg" alt=""&gt;&lt;/p&gt;</description></item><item><title>[2020] 가사 검색</title><link>https://lameld.github.io/kakao/2020_lyrics/</link><pubDate>Wed, 27 Nov 2019 11:21:48 +0900</pubDate><guid>https://lameld.github.io/kakao/2020_lyrics/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/60060"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;노래 가사에 사용된 단어들 중에 특정 키워드가 몇 개 포함되어 있는지 알 수 있는 프로그램&lt;/p&gt;</description></item><item><title>[2020] 기둥과 보 설치</title><link>https://lameld.github.io/kakao/2020_pole/</link><pubDate>Wed, 27 Nov 2019 11:22:18 +0900</pubDate><guid>https://lameld.github.io/kakao/2020_pole/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/60061"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;기둥과 보 조건&#10;&lt;ol&gt;&#10;&lt;li&gt;기둥 : 바닥 위에 있거나 보의 한쪽 끝 부분 위에 있거나, 또는 다른 기둥 위에 있어야 한다.&lt;/li&gt;&#10;&lt;li&gt;보 : 한쪽 끝 부분이 기둥 위에 있거나, 또는 양쪽 끝 부분이 다른 보와 동시에 연결되어 있어야 한다.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;위의 조건을 기준으로 설치/제거를 실시한다.&lt;/li&gt;&#10;&lt;li&gt;입력 : [ x, y , a, b ]&#10;&lt;ol&gt;&#10;&lt;li&gt;x, y : 설치/제거하는 물체의 좌표&lt;/li&gt;&#10;&lt;li&gt;a : 설치/제거할 구조물의 종류를 나타낸다. 0은 기둥, 1은 보&lt;/li&gt;&#10;&lt;li&gt;b : 설치/제거를 알려준다. 0은 삭제, 1은 설치&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;기둥 : (x, y) 좌표 위쪽으로 설치 또는 제거&lt;/li&gt;&#10;&lt;li&gt;보 : (x, y) 좌표 오른쪽으로 설치 또는 제거&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 풀이&lt;/p&gt;</description></item><item><title>[2020] 문자열 압축</title><link>https://lameld.github.io/kakao/2020_zip/</link><pubDate>Wed, 27 Nov 2019 11:21:08 +0900</pubDate><guid>https://lameld.github.io/kakao/2020_zip/</guid><description>&lt;p&gt;&lt;a href="https://programmers.co.kr/learn/courses/30/lessons/60057"&gt;문제 출처&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;문제 설명&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;데이터 처리 전문가가 되고 싶은 어피치는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자열에서 같은 값이 연속해서 나타나는 것을 그 문자의 개수와 반복되는 값으로 표현하여 더 짧은 문자열로 줄여서 표현하는 알고리즘을 공부하고 있습니다.&lt;/p&gt;</description></item></channel></rss>