<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>리치윈드 (RichWind)</title>
    <link>https://windflex.tistory.com/</link>
    <description>마흔쯤의 아빠들에게 필요한 인문/경제 공부 이야기.
공학자의 인문과 경제 이야기 </description>
    <language>ko</language>
    <pubDate>Sun, 14 Jun 2026 23:27:50 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>리치윈드 - windFlex</managingEditor>
    <image>
      <title>리치윈드 (RichWind)</title>
      <url>https://tistory1.daumcdn.net/tistory/2881870/attach/f5e4f3ff96d54148aa7b6c9e6d85f825</url>
      <link>https://windflex.tistory.com</link>
    </image>
    <item>
      <title>맥북에서 Docker 사용 최적화 방법 3가지</title>
      <link>https://windflex.tistory.com/239</link>
      <description>&lt;blockquote data-path-to-node=&quot;2&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;맥북에서 Docker Desktop을 구동할 때,&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-path-to-node=&quot;2&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;부담 스럽다고 느낀 사람 손 !!!&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 data-path-to-node=&quot;2&quot;&gt;  맥북에서 Docker Compose가 느린 이유와 최적의 해결책 3가지&lt;/h1&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;맥북으로 개발하다 보면 이런 고민에 빠지게 됩니다. &lt;b data-index-in-node=&quot;29&quot; data-path-to-node=&quot;3&quot;&gt;&quot;분명 사양은 좋은데, 왜 도커만 띄우면 팬이 돌고 빌드 속도가 느릴까?&quot;&lt;/b&gt; 맥(macOS)은 리눅스가 아니기 때문에, 도커를 실행하려면 내부적으로 가상 머신(VM)을 한 번 거쳐야 합니다. 특히 소스 코드를 실시간으로 컨테이너에 동기화하는 '파일 마운트' 과정에서 병목 현상이 심하죠. 오늘은 맥북 환경에서 &lt;b data-index-in-node=&quot;201&quot; data-path-to-node=&quot;3&quot;&gt;Docker Compose를 가장 쾌적하게 사용하는 3가지 방법&lt;/b&gt;을 정리해 드립니다.&lt;/p&gt;
&lt;hr data-path-to-node=&quot;4&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;5&quot; data-ke-size=&quot;size23&quot;&gt;1. 가장 쉬운 정공법: Docker Desktop (VirtioFS 설정)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;별도의 툴 설치 없이 기존 도커 데스크탑을 그대로 쓰고 싶다면 &lt;b data-index-in-node=&quot;35&quot; data-path-to-node=&quot;6&quot;&gt;설정 하나만 바꿔보세요.&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;최적화 핵심:&lt;/b&gt; Settings -&amp;gt; General -&amp;gt; Choose file sharing implementation에서 &lt;b data-index-in-node=&quot;68&quot; data-path-to-node=&quot;7,0,0&quot;&gt;VirtioFS&lt;/b&gt;를 선택하세요.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;왜 좋은가요?&lt;/b&gt; 애플의 가상화 프레임워크를 활용해 파일 읽기/쓰기 속도를 기존보다 최대 수 배 이상 높여줍니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;추천:&lt;/b&gt; &quot;이것저것 새로 깔기 귀찮다! 설정만으로 해결하고 싶다&quot;는 분들께 추천합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-path-to-node=&quot;8&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;9&quot; data-ke-size=&quot;size23&quot;&gt;2. 가벼움의 끝판왕: OrbStack (강력 추천)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;최근 맥 개발자들 사이에서 가장 핫한 대안입니다. &quot;Docker Desktop의 상위 호환&quot;이라는 평을 듣습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;특징:&lt;/b&gt; 도커 데스크탑보다 실행 속도가 압도적으로 빠르고 메모리 점유율이 매우 낮습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;장점:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;터미널에서 docker-compose up을 치는 순간 반응이 옵니다.&lt;/li&gt;
&lt;li&gt;배터리 효율이 좋아 카페에서 작업할 때 유리합니다.&lt;/li&gt;
&lt;li&gt;로컬 도메인(예: my-project.orb.local)을 자동으로 생성해 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,0&quot;&gt;추천:&lt;/b&gt; &quot;유료라도 상관없다(개인은 무료), 내 맥북의 퍼포먼스를 끝까지 뽑아 쓰고 싶다&quot;는 분들께 추천합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-path-to-node=&quot;12&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;13&quot; data-ke-size=&quot;size23&quot;&gt;3. 미니멀리스트를 위한 선택: Colima&lt;/h3&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;GUI 없이 터미널에서 모든 것을 제어하는 오픈소스 도구입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,0&quot;&gt;설치 방법:&lt;/b&gt; brew install colima&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,0&quot;&gt;장점:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;완전 무료이며 오픈소스입니다.&lt;/li&gt;
&lt;li&gt;불필요한 대시보드 앱이 없어 시스템 자원을 거의 사용하지 않습니다.&lt;/li&gt;
&lt;li&gt;colima start --cpu 4 --memory 8 처럼 자원 할당을 세밀하게 제어할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,2,0&quot;&gt;추천:&lt;/b&gt; &quot;커맨드 라인 환경을 사랑하고, 가장 순수한 리눅스 환경에 가깝게 도커를 쓰고 싶다&quot;는 개발자분들께 추천합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-path-to-node=&quot;16&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;17&quot; data-ke-size=&quot;size23&quot;&gt;  한 줄 요약: 어떤 것을 선택할까요?&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-path-to-node=&quot;18&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;선택지&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,1,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,1,0,0&quot;&gt;Docker Desktop&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,1,1,0&quot;&gt;가장 표준적, 쉬운 GUI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,1,2,0&quot;&gt;고사양 리소스 소모&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,2,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,2,0,0&quot;&gt;OrbStack&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,2,1,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,2,1,0&quot;&gt;압도적인 속도&lt;/b&gt;, 낮은 배터리 소모&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,2,2,0&quot;&gt;비즈니스 사용 시 유료&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,3,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,3,0,0&quot;&gt;Colima&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,3,1,0&quot;&gt;무료, 가벼움, 오픈소스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,3,2,0&quot;&gt;GUI 없음 (터미널 숙련도 필요)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-path-to-node=&quot;20&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-path-to-node=&quot;20&quot; data-ke-size=&quot;size23&quot;&gt;  마무리하며&lt;/h3&gt;
&lt;p data-path-to-node=&quot;21&quot; data-ke-size=&quot;size16&quot;&gt;맥북에서 도커가 느린 건 당신의 잘못이 아닙니다. 하지만 어떤 도구를 선택하느냐에 따라 빌드 시간 5분을 1분으로 단축할 수 있습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;개인적으로는 &lt;b data-index-in-node=&quot;7&quot; data-path-to-node=&quot;22&quot;&gt;OrbStack&lt;/b&gt;을 한 번 설치해 보시길 권장합니다. 처음 실행했을 때의 그 가벼움은 다시 Docker Desktop으로 돌아가지 못하게 만들거든요!&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;---&lt;/p&gt;
&lt;h2 data-path-to-node=&quot;2&quot; data-ke-size=&quot;size26&quot;&gt;  도구별 실행 및 Docker Compose 예제&lt;/h2&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;각 도구의 설치부터 가장 기초적인 Hello World 컨테이너 실행까지의 과정입니다.&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;4&quot; data-ke-size=&quot;size23&quot;&gt;1. Docker Desktop: 설정이 전부입니다&lt;/h3&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;Docker Desktop은 설치 후 GUI 설정만 바꿔주면 기존 docker 명령어를 그대로 사용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,0,0&quot;&gt;설정 변경:&lt;/b&gt; Settings &amp;gt; General &amp;gt; VirtioFS 체크 후 적용(Apply &amp;amp; Restart)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,0&quot;&gt;실행 예제:&lt;/b&gt;&lt;/li&gt;
&lt;li data-ved=&quot;0CAAQhtANahgKEwjG1e3KyOmSAxUAAAAAHQAAAAAQtAI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;&lt;span&gt;Bash&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;# 터미널에서 바로 실행
docker run hello-world
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-path-to-node=&quot;7&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;8&quot; data-ke-size=&quot;size23&quot;&gt;2. OrbStack: 설치 즉시 마이그레이션&lt;/h3&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;OrbStack은 설치하면 기존 Docker Desktop의 컨테이너를 자동으로 가져오기도 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;10&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,0,0&quot;&gt;설치:&lt;/b&gt; &lt;a href=&quot;https://orbstack.dev/&quot; data-ved=&quot;0CAAQ_4QMahgKEwjG1e3KyOmSAxUAAAAAHQAAAAAQtQI&quot; data-hveid=&quot;0&quot;&gt;OrbStack 홈페이지&lt;/a&gt;에서 다운로드 또는 brew install orbstack&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,1,0&quot;&gt;실행 예제:&lt;/b&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,1,2,0&quot;&gt;Tip:&lt;/b&gt; OrbStack은 실행 즉시 &lt;a href=&quot;http://getting-started.orb.local&quot;&gt;http://getting-started.orb.local&lt;/a&gt; 같은 로컬 도메인을 제공합니다.&lt;/li&gt;
&lt;li data-ved=&quot;0CAAQhtANahgKEwjG1e3KyOmSAxUAAAAAHQAAAAAQtgI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;&lt;span&gt;Bash&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;# OrbStack 앱 실행 후 터미널에서
docker run -d -p 80:80 docker/getting-started
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-path-to-node=&quot;11&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;12&quot; data-ke-size=&quot;size23&quot;&gt;3. Colima: 터미널 기반의 정석 (Hello World 예제)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;질문하신 Colima에서 도커를 띄우는 전체 과정입니다. Colima는 가상 머신(VM)을 먼저 띄운 뒤 도커 명령어를 사용한다는 점이 핵심입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;14&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,0,0&quot;&gt;1단계: 설치&lt;/b&gt;&lt;/li&gt;
&lt;li data-ved=&quot;0CAAQhtANahgKEwjG1e3KyOmSAxUAAAAAHQAAAAAQtwI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;&lt;span&gt;Bash&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;brew install colima docker docker-compose
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,1,0&quot;&gt;2단계: VM 시작 (최적화 옵션 포함)&lt;/b&gt;&lt;/li&gt;
&lt;li data-ved=&quot;0CAAQhtANahgKEwjG1e3KyOmSAxUAAAAAHQAAAAAQuAI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;&lt;span&gt;Bash&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dsconfig&quot;&gt;&lt;code&gt;# CPU 2코어, 메모리 4GB, Rosetta(M1/M2/M3용 가속) 활성화
colima start --cpu 2 --memory 4 --arch aarch64 --vm-type=vz --vz-rosetta
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,2,0&quot;&gt;3단계: 컨테이너 실행&lt;/b&gt;&lt;/li&gt;
&lt;li data-ved=&quot;0CAAQhtANahgKEwjG1e3KyOmSAxUAAAAAHQAAAAAQuQI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;&lt;span&gt;Bash&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;# 가장 기본적인 Hello World 이미지 실행
docker run hello-world
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,3,0&quot;&gt;4단계: Docker Compose 실행&lt;/b&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwjG1e3KyOmSAxUAAAAAHQAAAAAQuwI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;&lt;span&gt;Bash&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# 실행 명령어
docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li data-ved=&quot;0CAAQhtANahgKEwjG1e3KyOmSAxUAAAAAHQAAAAAQugI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;&lt;span&gt;YAML&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;# docker-compose.yml 예시
services:
  web:
    image: nginx:latest
    ports:
      - &quot;8080:80&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-path-to-node=&quot;15&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;16&quot; data-ke-size=&quot;size23&quot;&gt;  실무 꿀팁: 어떤 상황에 무엇을 쓸까?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;17&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,0,0&quot;&gt;빠른 피드백이 중요한 프론트엔드 개발:&lt;/b&gt; 파일 수정이 즉시 반영되어야 하므로 &lt;b data-index-in-node=&quot;42&quot; data-path-to-node=&quot;17,0,0&quot;&gt;OrbStack&lt;/b&gt;이 가장 유리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,1,0&quot;&gt;서버 리소스를 아껴야 하는 복합 마이크로서비스:&lt;/b&gt; 여러 개의 컨테이너를 띄워야 한다면 가벼운 &lt;b data-index-in-node=&quot;51&quot; data-path-to-node=&quot;17,1,0&quot;&gt;Colima&lt;/b&gt;가 정답입니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,2,0&quot;&gt;도커가 처음인 입문자:&lt;/b&gt; 오류 메시지를 시각적으로 볼 수 있는 &lt;b data-index-in-node=&quot;34&quot; data-path-to-node=&quot;17,2,0&quot;&gt;Docker Desktop&lt;/b&gt;으로 시작하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-path-to-node=&quot;18&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;19&quot; data-ke-size=&quot;size23&quot;&gt;⚠️ 주의사항&lt;/h3&gt;
&lt;p data-path-to-node=&quot;20&quot; data-ke-size=&quot;size16&quot;&gt;여러 도구를 동시에 실행하면 포트 충돌이나 리소스 낭비가 발생할 수 있습니다. 하나를 선택했다면 다른 도구는 반드시 &lt;b data-index-in-node=&quot;65&quot; data-path-to-node=&quot;20&quot;&gt;종료(Quit/Stop)&lt;/b&gt; 상태로 두는 것이 좋습니다.&lt;/p&gt;</description>
      <category>colima</category>
      <category>compose</category>
      <category>Docker</category>
      <category>DockerDesktop</category>
      <category>orbStack</category>
      <category>도커</category>
      <category>도커컴포즈</category>
      <category>맥북</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/239</guid>
      <comments>https://windflex.tistory.com/239#entry239comment</comments>
      <pubDate>Sat, 21 Feb 2026 12:28:03 +0900</pubDate>
    </item>
    <item>
      <title>   Claude Code Tutorial-2 (클로드 코드 튜터리얼)</title>
      <link>https://windflex.tistory.com/238</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1010&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccv4y9/dJMb99SU5Ii/mOT3VMZukkTWmQSi1UcNi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccv4y9/dJMb99SU5Ii/mOT3VMZukkTWmQSi1UcNi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccv4y9/dJMb99SU5Ii/mOT3VMZukkTWmQSi1UcNi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fccv4y9%2FdJMb99SU5Ii%2FmOT3VMZukkTWmQSi1UcNi0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1010&quot; height=&quot;556&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1010&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&quot;blog-wrap&quot;&gt;
&lt;div class=&quot;bw-footer&quot;&gt;
&lt;p class=&quot;bw-footer-text&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;Claude Code 실전 튜터리얼 2편 — Skills &amp; 병렬 에이전트&lt;/title&gt;
&lt;link href=&quot;https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@400;600;700&amp;family=JetBrains+Mono:wght@400;600&amp;family=Pretendard:wght@300;400;500;600;700&amp;display=swap&quot; rel=&quot;stylesheet&quot;&gt;
&lt;style&gt;
  .blog-wrap,
  .blog-wrap *,
  .blog-wrap *::before,
  .blog-wrap *::after {
    box-sizing: border-box !important;
  }

  .blog-wrap {
    background: #f8f7f4 !important;
    color: #1a1814 !important;
    max-width: 780px !important;
    margin: 0 auto !important;
    padding: 0 !important;
    line-height: 1.8 !important;
    font-family: 'Pretendard', -apple-system, sans-serif !important;
  }

  /* ===== HERO ===== */
  .bw-hero {
    background: linear-gradient(160deg, #0f2a1a 0%, #1a3a28 50%, #0f2030 100%) !important;
    padding: 80px 40px 70px !important;
    text-align: center !important;
    border-radius: 16px !important;
    margin-bottom: 56px !important;
    position: relative !important;
    overflow: hidden !important;
  }

  .bw-badge {
    display: inline-block !important;
    background: rgba(255,255,255,0.1) !important;
    border: 1px solid rgba(255,255,255,0.2) !important;
    border-radius: 100px !important;
    padding: 5px 16px !important;
    font-size: 12px !important;
    color: #a0ffcc !important;
    letter-spacing: 0.06em !important;
    margin-bottom: 12px !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-part-label {
    display: block !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    color: rgba(255,255,255,0.35) !important;
    letter-spacing: 0.15em !important;
    text-transform: uppercase !important;
    margin-bottom: 20px !important;
  }

  .bw-hero-title {
    font-family: 'Noto Serif KR', serif !important;
    font-size: 2.3rem !important;
    font-weight: 700 !important;
    color: #ffffff !important;
    line-height: 1.25 !important;
    margin: 0 0 20px !important;
  }

  .bw-ht-green  { color: #6fffb0 !important; }
  .bw-ht-yellow { color: #ffe566 !important; }

  .bw-hero-sub {
    font-size: 1.02rem !important;
    color: rgba(255,255,255,0.55) !important;
    margin: 0 auto 40px !important;
    max-width: 520px !important;
    font-family: 'Pretendard', sans-serif !important;
    line-height: 1.7 !important;
  }

  .bw-prev-link {
    display: inline-flex !important;
    align-items: center !important;
    gap: 6px !important;
    font-size: 12px !important;
    color: rgba(255,255,255,0.4) !important;
    font-family: 'Pretendard', sans-serif !important;
    margin-bottom: 32px !important;
  }

  .bw-stats {
    display: flex !important;
    justify-content: center !important;
    gap: 48px !important;
  }

  .bw-stat-num {
    display: block !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 2rem !important;
    font-weight: 600 !important;
    color: #6fffb0 !important;
    line-height: 1 !important;
    margin-bottom: 4px !important;
  }

  .bw-stat-label {
    display: block !important;
    font-size: 11px !important;
    color: rgba(255,255,255,0.38) !important;
    letter-spacing: 0.1em !important;
    text-transform: uppercase !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  /* ===== RECAP BOX ===== */
  .bw-recap {
    background: #eef8f2 !important;
    border: 1px solid #b8ddc8 !important;
    border-left: 4px solid #1a7a42 !important;
    border-radius: 0 12px 12px 0 !important;
    padding: 20px 24px !important;
    margin-bottom: 48px !important;
  }

  .bw-recap-label {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.12em !important;
    text-transform: uppercase !important;
    color: #1a7a42 !important;
    margin-bottom: 12px !important;
    display: block !important;
  }

  .bw-recap-grid {
    display: grid !important;
    grid-template-columns: repeat(4, 1fr) !important;
    gap: 10px !important;
  }

  .bw-recap-item {
    background: #f8fdf9 !important;
    border: 1px solid #c8e8d8 !important;
    border-radius: 8px !important;
    padding: 10px 12px !important;
    font-size: 0.82rem !important;
    color: #1a5c34 !important;
    font-family: 'Pretendard', sans-serif !important;
    text-align: center !important;
  }

  .bw-recap-item .ri-icon {
    display: block !important;
    font-size: 1.1rem !important;
    margin-bottom: 4px !important;
  }

  /* ===== TOC ===== */
  .bw-toc {
    background: #f0ede8 !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 12px !important;
    padding: 22px 26px !important;
    margin-bottom: 56px !important;
  }

  .bw-toc-title {
    font-size: 11px !important;
    font-weight: 600 !important;
    letter-spacing: 0.12em !important;
    text-transform: uppercase !important;
    color: #8a8480 !important;
    margin: 0 0 14px !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-toc-list {
    list-style: none !important;
    padding: 0 !important;
    margin: 0 !important;
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 5px !important;
  }

  .bw-toc-item { margin: 0 !important; padding: 0 !important; list-style: none !important; }

  .bw-toc-link {
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
    font-size: 0.88rem !important;
    color: #4a4540 !important;
    text-decoration: none !important;
    padding: 5px 0 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-toc-num {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    color: #1a7a42 !important;
    background: rgba(26,122,66,0.1) !important;
    border-radius: 4px !important;
    padding: 2px 6px !important;
    flex-shrink: 0 !important;
  }

  /* ===== SECTION ===== */
  .bw-section { margin-bottom: 72px !important; }

  .bw-section-header {
    display: flex !important;
    align-items: flex-start !important;
    gap: 16px !important;
    margin-bottom: 20px !important;
    padding-bottom: 18px !important;
    border-bottom: 2px solid #e8e4dd !important;
  }

  .bw-step-tag {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    font-weight: 600 !important;
    letter-spacing: 0.08em !important;
    color: #1a7a42 !important;
    background: rgba(26,122,66,0.08) !important;
    border: 1px solid rgba(26,122,66,0.2) !important;
    border-radius: 6px !important;
    padding: 4px 10px !important;
    white-space: nowrap !important;
    margin-top: 6px !important;
    flex-shrink: 0 !important;
  }

  .bw-section-title {
    font-family: 'Noto Serif KR', serif !important;
    font-size: 1.55rem !important;
    font-weight: 700 !important;
    color: #1a1814 !important;
    line-height: 1.3 !important;
    margin: 0 !important;
  }

  .bw-st-green  { color: #1a7a42 !important; }
  .bw-st-orange { color: #c4500a !important; }
  .bw-st-purple { color: #4a3fb5 !important; }
  .bw-st-yellow { color: #9a6e00 !important; }

  .bw-desc {
    font-size: 1.02rem !important;
    color: #4a4540 !important;
    margin: 0 0 20px !important;
    line-height: 1.75 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-p {
    color: #1a1814 !important;
    margin: 0 0 14px !important;
    font-size: 1rem !important;
    line-height: 1.8 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-h3 {
    font-size: 1.02rem !important;
    font-weight: 700 !important;
    color: #1a1814 !important;
    margin: 26px 0 10px !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  /* ===== TERMINAL ===== */
  .bw-terminal {
    background: #1a1c18 !important;
    border-radius: 12px !important;
    overflow: hidden !important;
    margin: 18px 0 !important;
    box-shadow: 0 4px 20px rgba(0,0,0,0.15) !important;
  }

  .bw-term-bar {
    display: flex !important;
    align-items: center !important;
    gap: 7px !important;
    padding: 10px 16px !important;
    background: #272920 !important;
    border-bottom: 1px solid #363830 !important;
  }

  .bw-dot { width: 11px !important; height: 11px !important; border-radius: 50% !important; flex-shrink: 0 !important; display: inline-block !important; }
  .bw-dot-r { background: #ff5f57 !important; }
  .bw-dot-y { background: #febc2e !important; }
  .bw-dot-g { background: #28c840 !important; }

  .bw-term-title {
    flex: 1 !important;
    text-align: center !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    color: #6a7060 !important;
  }

  .bw-term-body {
    padding: 18px 22px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 13px !important;
    line-height: 1.8 !important;
    color: #dde8d8 !important;
  }

  .tc { color: #6fffb0 !important; display: block !important; }
  .tc::before { content: '$ ' !important; color: #4a5040 !important; }
  .tp { color: #b0a0ff !important; display: block !important; }
  .tp::before { content: '&gt; ' !important; color: #4a5040 !important; }
  .to { color: #9aa890 !important; display: block !important; }
  .ts { color: #6fffb0 !important; display: block !important; }
  .ts::before { content: '✓ ' !important; }
  .te { color: #ff8080 !important; display: block !important; }
  .te::before { content: '✗ ' !important; }
  .tm { color: #4a5040 !important; display: block !important; }
  .tm::before { content: '# ' !important; }
  .tk { color: #ffe566 !important; display: block !important; }

  /* ===== INLINE CODE ===== */
  .bw-code {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 0.87em !important;
    background: #ede9e2 !important;
    border: 1px solid #d0ccc4 !important;
    border-radius: 5px !important;
    padding: 2px 7px !important;
    color: #1a7a42 !important;
  }

  /* ===== CALLOUT ===== */
  .bw-callout {
    display: flex !important;
    gap: 12px !important;
    align-items: flex-start !important;
    border-radius: 10px !important;
    padding: 14px 18px !important;
    margin: 16px 0 !important;
    font-size: 0.93rem !important;
    line-height: 1.7 !important;
  }

  .bw-callout-tip  { background: #edf7f1 !important; border: 1px solid #b8e0c8 !important; }
  .bw-callout-warn { background: #fef8ec !important; border: 1px solid #f5dc90 !important; }
  .bw-callout-info { background: #eef0fb !important; border: 1px solid #b8bef0 !important; }
  .bw-callout-err  { background: #fdf0f0 !important; border: 1px solid #f0c0c0 !important; }

  .bw-callout-icon { font-size: 1.05rem !important; flex-shrink: 0 !important; margin-top: 1px !important; }
  .bw-callout-tip  .bw-ct { color: #1a5c34 !important; font-family: 'Pretendard', sans-serif !important; }
  .bw-callout-warn .bw-ct { color: #6b4c00 !important; font-family: 'Pretendard', sans-serif !important; }
  .bw-callout-info .bw-ct { color: #2a3090 !important; font-family: 'Pretendard', sans-serif !important; }
  .bw-callout-err  .bw-ct { color: #8a1010 !important; font-family: 'Pretendard', sans-serif !important; }

  /* ===== FILE TREE ===== */
  .bw-filetree {
    background: #f4f1ec !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 10px !important;
    padding: 18px 20px !important;
    margin: 16px 0 !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 13px !important;
    line-height: 1.9 !important;
    color: #4a4540 !important;
  }

  .ft-dir   { color: #4a3fb5 !important; font-weight: 600 !important; display: block !important; }
  .ft-file  { color: #1a7a42 !important; display: block !important; }
  .ft-note  { color: #8a8480 !important; font-size: 11px !important; }
  .ft-req   { color: #c4500a !important; font-weight: 600 !important; }

  /* ===== COMPARE ===== */
  .bw-compare {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 14px !important;
    margin: 18px 0 !important;
  }

  .bw-compare-card { border-radius: 10px !important; padding: 18px !important; }
  .bw-cb { background: #fdf0f0 !important; border: 1px solid #f0c0c0 !important; }
  .bw-cg { background: #f0f8f3 !important; border: 1px solid #a8dbb8 !important; }

  .bw-compare-label {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.1em !important;
    text-transform: uppercase !important;
    margin-bottom: 10px !important;
    display: block !important;
  }
  .bw-cb .bw-compare-label { color: #c03030 !important; }
  .bw-cg .bw-compare-label { color: #1a7a42 !important; }

  .bw-compare-code {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 12px !important;
    color: #4a4540 !important;
    line-height: 1.65 !important;
    white-space: pre-line !important;
    display: block !important;
  }

  .bw-compare-note {
    font-size: 11.5px !important;
    margin-top: 10px !important;
    padding-top: 10px !important;
    border-top: 1px solid rgba(0,0,0,0.08) !important;
    font-family: 'Pretendard', sans-serif !important;
    display: block !important;
  }
  .bw-cb .bw-compare-note { color: #c03030 !important; }
  .bw-cg .bw-compare-note { color: #1a7a42 !important; }

  /* ===== TABLE ===== */
  .bw-table {
    width: 100% !important;
    border-collapse: collapse !important;
    margin: 16px 0 !important;
    font-size: 0.92rem !important;
  }

  .bw-table th {
    text-align: left !important;
    padding: 9px 16px !important;
    background: #e8e4dd !important;
    color: #4a4540 !important;
    font-weight: 600 !important;
    font-size: 11px !important;
    letter-spacing: 0.06em !important;
    text-transform: uppercase !important;
    border-bottom: 2px solid #d0ccc4 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-table td {
    padding: 10px 16px !important;
    border-bottom: 1px solid #e8e4dd !important;
    color: #4a4540 !important;
    vertical-align: top !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-table td:first-child {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 12px !important;
    color: #4a3fb5 !important;
    white-space: nowrap !important;
  }

  .bw-table tr:last-child td { border-bottom: none !important; }
  .td-green { color: #1a7a42 !important; font-weight: 600 !important; }

  /* ===== PARALLEL VIZ ===== */
  .bw-parallel {
    background: #f4f1ec !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 12px !important;
    padding: 24px !important;
    margin: 18px 0 !important;
  }

  .bw-parallel-title {
    font-size: 11px !important;
    font-weight: 600 !important;
    letter-spacing: 0.1em !important;
    text-transform: uppercase !important;
    color: #8a8480 !important;
    margin-bottom: 16px !important;
    display: block !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-parallel-row {
    display: flex !important;
    align-items: center !important;
    gap: 12px !important;
    margin-bottom: 16px !important;
  }

  .bw-parallel-row:last-child { margin-bottom: 0 !important; }

  .bw-parallel-label {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    color: #8a8480 !important;
    width: 80px !important;
    flex-shrink: 0 !important;
  }

  .bw-parallel-bars {
    flex: 1 !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 6px !important;
  }

  .bw-bar {
    height: 28px !important;
    border-radius: 6px !important;
    display: flex !important;
    align-items: center !important;
    padding: 0 12px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    color: #fff !important;
  }

  .bw-bar-seq { background: #c4500a !important; }
  .bw-bar-par1 { background: #1a7a42 !important; width: 25% !important; }
  .bw-bar-par2 { background: #4a3fb5 !important; width: 25% !important; }
  .bw-bar-par3 { background: #9a6e00 !important; width: 25% !important; }
  .bw-bar-par4 { background: #2a7a8a !important; width: 25% !important; }

  .bw-parallel-result {
    font-family: 'Pretendard', sans-serif !important;
    font-size: 11px !important;
    color: #8a8480 !important;
    text-align: right !important;
    margin-top: 8px !important;
    display: block !important;
  }

  /* ===== AGENT CARD ===== */
  .bw-agent-grid {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 12px !important;
    margin: 18px 0 !important;
  }

  .bw-agent-card {
    background: #f0ede8 !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 10px !important;
    padding: 16px !important;
  }

  .bw-agent-name {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 12px !important;
    color: #4a3fb5 !important;
    margin-bottom: 6px !important;
    display: block !important;
  }

  .bw-agent-type {
    font-size: 10px !important;
    font-family: 'JetBrains Mono', monospace !important;
    color: #ffffff !important;
    border-radius: 4px !important;
    padding: 2px 7px !important;
    display: inline-block !important;
    margin-bottom: 8px !important;
  }

  .at-task    { background: #1a7a42 !important; }
  .at-explore { background: #4a3fb5 !important; }

  .bw-agent-desc {
    font-size: 0.83rem !important;
    color: #6a6460 !important;
    line-height: 1.5 !important;
    display: block !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  /* ===== SUMMARY CARDS ===== */
  .bw-summary-grid {
    display: grid !important;
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 12px !important;
    margin: 24px 0 !important;
  }

  .bw-summary-card {
    background: #f0ede8 !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 12px !important;
    padding: 18px !important;
  }

  .bw-sc-icon  { font-size: 1.3rem !important; margin-bottom: 8px !important; display: block !important; }
  .bw-sc-title { font-weight: 700 !important; font-size: 0.93rem !important; color: #1a1814 !important; margin-bottom: 5px !important; display: block !important; font-family: 'Pretendard', sans-serif !important; }
  .bw-sc-desc  { font-size: 0.83rem !important; color: #6a6460 !important; line-height: 1.5 !important; display: block !important; font-family: 'Pretendard', sans-serif !important; }

  /* ===== FULL ROADMAP ===== */
  .bw-roadmap {
    background: #1a1c18 !important;
    border-radius: 12px !important;
    overflow: hidden !important;
    margin: 18px 0 !important;
  }

  .bw-roadmap-bar {
    background: #272920 !important;
    border-bottom: 1px solid #363830 !important;
    padding: 10px 18px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    color: #6a7060 !important;
  }

  .bw-roadmap-body {
    padding: 22px 24px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 13px !important;
    line-height: 2 !important;
  }

  .rm-done   { color: #6fffb0 !important; display: block !important; }
  .rm-done::before { content: '✓ ' !important; color: #4a5040 !important; }
  .rm-new    { color: #ffe566 !important; display: block !important; }
  .rm-new::before  { content: '★ ' !important; color: #4a5040 !important; }
  .rm-next   { color: #5a6050 !important; display: block !important; }
  .rm-next::before { content: '○ ' !important; color: #3a4030 !important; }
  .rm-label  { color: #4a5040 !important; font-size: 11px !important; display: block !important; margin: 8px 0 4px !important; }

  /* ===== DIVIDER ===== */
  .bw-divider {
    height: 1px !important;
    background: linear-gradient(to right, transparent, #d8d3cb, transparent) !important;
    margin: 56px 0 !important;
    border: none !important;
  }

  /* ===== FOOTER ===== */
  .bw-footer {
    background: #f0ede8 !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 12px !important;
    padding: 26px !important;
    text-align: center !important;
    margin-top: 48px !important;
  }

  .bw-footer-text {
    color: #8a8480 !important;
    font-size: 0.875rem !important;
    margin: 0 !important;
    line-height: 1.7 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-footer-link { color: #1a7a42 !important; }

  @media (max-width: 600px) {
    .bw-hero { padding: 48px 20px 40px !important; }
    .bw-hero-title { font-size: 1.7rem !important; }
    .bw-stats { gap: 24px !important; }
    .bw-compare { grid-template-columns: 1fr !important; }
    .bw-agent-grid { grid-template-columns: 1fr !important; }
    .bw-summary-grid { grid-template-columns: 1fr !important; }
    .bw-toc-list { grid-template-columns: 1fr !important; }
    .bw-recap-grid { grid-template-columns: 1fr 1fr !important; }
  }
&lt;/style&gt;

&lt;div class=&quot;blog-wrap&quot;&gt;

  &lt;!-- HERO --&gt;
  &lt;div class=&quot;bw-hero&quot;&gt;
    &lt;div class=&quot;bw-badge&quot;&gt;  실전 튜터리얼 2편&lt;/div&gt;
    &lt;span class=&quot;bw-part-label&quot;&gt;PART 02 / 02&lt;/span&gt;
    &lt;h1 class=&quot;bw-hero-title&quot;&gt;
      &lt;span class=&quot;bw-ht-green&quot;&gt;Skills&lt;/span&gt; &amp;amp;&lt;br&gt;
      &lt;span class=&quot;bw-ht-yellow&quot;&gt;병렬 에이전트&lt;/span&gt; 완전 정복
    &lt;/h1&gt;
    &lt;p class=&quot;bw-hero-sub&quot;&gt;CLAUDE.md·Plan Mode·Hooks를 익혔다면 이제 다음 단계로 — 재사용 가능한 Skills와 동시 실행 에이전트로 개발 속도를 극대화합니다.&lt;/p&gt;
    &lt;div class=&quot;bw-prev-link&quot;&gt;← 1편: CLAUDE.md · Plan Mode · Hooks · @ 파일 참조&lt;/div&gt;
    &lt;div class=&quot;bw-stats&quot;&gt;
      &lt;div&gt;
        &lt;span class=&quot;bw-stat-num&quot;&gt;2&lt;/span&gt;
        &lt;span class=&quot;bw-stat-label&quot;&gt;핵심 기능&lt;/span&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;span class=&quot;bw-stat-num&quot;&gt;4x&lt;/span&gt;
        &lt;span class=&quot;bw-stat-label&quot;&gt;병렬 실행&lt;/span&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;span class=&quot;bw-stat-num&quot;&gt;∞&lt;/span&gt;
        &lt;span class=&quot;bw-stat-label&quot;&gt;재사용 가능&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- RECAP --&gt;
  &lt;div class=&quot;bw-recap&quot;&gt;
    &lt;span class=&quot;bw-recap-label&quot;&gt;1편 복습 — 오늘 이것들을 알고 있다고 가정합니다&lt;/span&gt;
    &lt;div class=&quot;bw-recap-grid&quot;&gt;
      &lt;div class=&quot;bw-recap-item&quot;&gt;&lt;span class=&quot;ri-icon&quot;&gt; &lt;/span&gt;CLAUDE.md&lt;/div&gt;
      &lt;div class=&quot;bw-recap-item&quot;&gt;&lt;span class=&quot;ri-icon&quot;&gt; &lt;/span&gt;Plan Mode&lt;/div&gt;
      &lt;div class=&quot;bw-recap-item&quot;&gt;&lt;span class=&quot;ri-icon&quot;&gt;@&lt;/span&gt;파일 참조&lt;/div&gt;
      &lt;div class=&quot;bw-recap-item&quot;&gt;&lt;span class=&quot;ri-icon&quot;&gt; &lt;/span&gt;Hooks&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- TOC --&gt;
  &lt;div class=&quot;bw-toc&quot;&gt;
    &lt;div class=&quot;bw-toc-title&quot;&gt;목차&lt;/div&gt;
    &lt;ul class=&quot;bw-toc-list&quot;&gt;
      &lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a href=&quot;#s1&quot; class=&quot;bw-toc-link&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;01&lt;/span&gt; Skills란 무엇인가&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a href=&quot;#s2&quot; class=&quot;bw-toc-link&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;02&lt;/span&gt; SKILL.md 구조 이해&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a href=&quot;#s3&quot; class=&quot;bw-toc-link&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;03&lt;/span&gt; 첫 Skill 직접 만들기&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a href=&quot;#s4&quot; class=&quot;bw-toc-link&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;04&lt;/span&gt; 실수: Unknown skill 에러&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a href=&quot;#s5&quot; class=&quot;bw-toc-link&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;05&lt;/span&gt; 병렬 에이전트란&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a href=&quot;#s6&quot; class=&quot;bw-toc-link&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;06&lt;/span&gt; 병렬 실행 직접 해보기&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a href=&quot;#s7&quot; class=&quot;bw-toc-link&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;07&lt;/span&gt; Task vs Explore 에이전트&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a href=&quot;#s8&quot; class=&quot;bw-toc-link&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;08&lt;/span&gt; 전체 로드맵 총정리&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;

  &lt;!-- STEP 1 --&gt;
  &lt;div class=&quot;bw-section&quot; id=&quot;s1&quot;&gt;
    &lt;div class=&quot;bw-section-header&quot;&gt;
      &lt;span class=&quot;bw-step-tag&quot;&gt;STEP 01&lt;/span&gt;
      &lt;h2 class=&quot;bw-section-title&quot;&gt;&lt;span class=&quot;bw-st-green&quot;&gt;Skills&lt;/span&gt;란 무엇인가&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p class=&quot;bw-desc&quot;&gt;Skills는 Claude에게 특정 작업 방법을 가르쳐두는 재사용 가능한 지식 패키지입니다. CLAUDE.md와 헷갈리기 쉬운데, 역할이 명확히 다릅니다.&lt;/p&gt;

    &lt;table class=&quot;bw-table&quot;&gt;
      &lt;thead&gt;&lt;tr&gt;&lt;th&gt;구분&lt;/th&gt;&lt;th&gt;CLAUDE.md&lt;/th&gt;&lt;th&gt;Skills&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;역할&lt;/td&gt;&lt;td&gt;프로젝트 정체성·규칙&lt;/td&gt;&lt;td&gt;특정 작업의 실행 방법&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;로딩&lt;/td&gt;&lt;td&gt;항상 자동 로딩&lt;/td&gt;&lt;td&gt;&lt;span class=&quot;td-green&quot;&gt;필요할 때만 로딩&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;범위&lt;/td&gt;&lt;td&gt;전체 프로젝트&lt;/td&gt;&lt;td&gt;특정 작업 유형&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;스크립트&lt;/td&gt;&lt;td&gt;불가&lt;/td&gt;&lt;td&gt;&lt;span class=&quot;td-green&quot;&gt;Python·Shell 번들 가능&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;저장 위치&lt;/td&gt;&lt;td&gt;.claude/CLAUDE.md&lt;/td&gt;&lt;td&gt;.claude/skills/이름/SKILL.md&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;div class=&quot;bw-callout bw-callout-tip&quot;&gt;
      &lt;span class=&quot;bw-callout-icon&quot;&gt; &lt;/span&gt;
      &lt;span class=&quot;bw-ct&quot;&gt;&lt;strong&gt;언제 만드나?&lt;/strong&gt; 같은 프롬프트를 여러 대화에서 반복해서 타이핑하고 있다면, Skill을 만들 때가 된 겁니다. &quot;코드 리뷰해줘&quot;, &quot;PR 요약해줘&quot; 같은 반복 작업이 대표적입니다.&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;hr class=&quot;bw-divider&quot;&gt;

  &lt;!-- STEP 2 --&gt;
  &lt;div class=&quot;bw-section&quot; id=&quot;s2&quot;&gt;
    &lt;div class=&quot;bw-section-header&quot;&gt;
      &lt;span class=&quot;bw-step-tag&quot;&gt;STEP 02&lt;/span&gt;
      &lt;h2 class=&quot;bw-section-title&quot;&gt;&lt;span class=&quot;bw-st-green&quot;&gt;SKILL.md&lt;/span&gt; 구조 이해&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p class=&quot;bw-desc&quot;&gt;모든 Skill은 폴더 안의 &lt;span class=&quot;bw-code&quot;&gt;SKILL.md&lt;/span&gt; 파일로 정의됩니다. 파일명이 아닌 &lt;strong&gt;폴더명&lt;/strong&gt;이 Skill 이름이 됩니다.&lt;/p&gt;

    &lt;div class=&quot;bw-filetree&quot;&gt;
      &lt;span class=&quot;ft-dir&quot;&gt;.claude/skills/&lt;/span&gt;
      &lt;span class=&quot;ft-dir&quot;&gt;└── code-reviewer/        &lt;span class=&quot;ft-note&quot;&gt;← 폴더명 = Skill 이름&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;ft-file&quot;&gt;    ├── SKILL.md          &lt;span class=&quot;ft-req&quot;&gt;← 필수&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;ft-file&quot;&gt;    ├── scripts/          &lt;span class=&quot;ft-note&quot;&gt;← 번들 스크립트 (선택)&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;ft-file&quot;&gt;    │   └── lint.sh&lt;/span&gt;
      &lt;span class=&quot;ft-file&quot;&gt;    └── resources/        &lt;span class=&quot;ft-note&quot;&gt;← 참고 자료 (선택)&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;ft-file&quot;&gt;        └── checklist.md&lt;/span&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-h3&quot;&gt;SKILL.md 기본 형식&lt;/div&gt;

    &lt;div class=&quot;bw-terminal&quot;&gt;
      &lt;div class=&quot;bw-term-bar&quot;&gt;
        &lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&lt;/div&gt;
        &lt;span class=&quot;bw-term-title&quot;&gt;.claude/skills/code-reviewer/SKILL.md&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-term-body&quot;&gt;
        &lt;div class=&quot;to&quot;&gt;---&lt;/div&gt;
        &lt;div class=&quot;tk&quot;&gt;name: code-reviewer&lt;/div&gt;
        &lt;div class=&quot;tk&quot;&gt;description: Python 코드 품질 리뷰. 타입힌트·docstring·&lt;/div&gt;
        &lt;div class=&quot;tk&quot;&gt;             예외처리를 검토할 때 사용.&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;---&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;tm&quot;&gt;↑ frontmatter: Claude가 언제 이 Skill을 쓸지 판단하는 기준&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;to&quot;&gt;## 코드 리뷰 체크리스트&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;to&quot;&gt;리뷰 시 반드시 아래 순서로 확인한다:&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;1. 타입 힌트 — 모든 함수에 있는지&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;2. Docstring — Args, Returns, Raises 포함 여부&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;3. 예외 처리 — ValueError/TypeError 적절히 발생하는지&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;...&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;tm&quot;&gt;↑ 본문: 실제 Claude에게 주입되는 지시사항&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-callout bw-callout-info&quot;&gt;
      &lt;span class=&quot;bw-callout-icon&quot;&gt;⚙️&lt;/span&gt;
      &lt;span class=&quot;bw-ct&quot;&gt;&lt;strong&gt;작동 원리:&lt;/strong&gt; Claude Code는 SKILL.md의 frontmatter를 스캔해서 사용 가능한 Skill 목록을 만들고, 실제 호출 시 SKILL.md 본문을 대화 컨텍스트에 주입합니다. 메인 프롬프트를 항상 가볍게 유지하면서 필요할 때만 로딩하는 구조입니다.&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;hr class=&quot;bw-divider&quot;&gt;

  &lt;!-- STEP 3 --&gt;
  &lt;div class=&quot;bw-section&quot; id=&quot;s3&quot;&gt;
    &lt;div class=&quot;bw-section-header&quot;&gt;
      &lt;span class=&quot;bw-step-tag&quot;&gt;STEP 03&lt;/span&gt;
      &lt;h2 class=&quot;bw-section-title&quot;&gt;첫 Skill &lt;span class=&quot;bw-st-green&quot;&gt;직접 만들기&lt;/span&gt;&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p class=&quot;bw-desc&quot;&gt;계산기 프로젝트에 코드 리뷰어 Skill을 만들어봅니다. 순서가 중요합니다.&lt;/p&gt;

    &lt;div class=&quot;bw-h3&quot;&gt;1단계 — 폴더 먼저 생성 (터미널에서)&lt;/div&gt;
    &lt;div class=&quot;bw-terminal&quot;&gt;
      &lt;div class=&quot;bw-term-bar&quot;&gt;
        &lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&lt;/div&gt;
        &lt;span class=&quot;bw-term-title&quot;&gt;Terminal — Claude Code 밖에서&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-term-body&quot;&gt;
        &lt;div class=&quot;tc&quot;&gt;mkdir -p .claude/skills/code-reviewer&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-h3&quot;&gt;2단계 — Claude Code 세션에서 SKILL.md 작성&lt;/div&gt;
    &lt;div class=&quot;bw-terminal&quot;&gt;
      &lt;div class=&quot;bw-term-bar&quot;&gt;
        &lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&lt;/div&gt;
        &lt;span class=&quot;bw-term-title&quot;&gt;Claude Code&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-term-body&quot;&gt;
        &lt;div class=&quot;tp&quot;&gt;.claude/skills/code-reviewer/SKILL.md 파일을 만들어줘:&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;to&quot;&gt;---&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;name: code-reviewer&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;description: Python 코드 품질 리뷰. 타입힌트·docstring·&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;             예외처리·Pythonic 코드를 검토할 때 사용.&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;---&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;to&quot;&gt;## 코드 리뷰 체크리스트&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;1. 타입 힌트 [심각도: 상/중/하]&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;2. Docstring&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;3. 예외 처리&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;4. Pythonic 스타일&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;5. 로깅 (print 금지)&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;각 항목에 수정 코드 예시를 함께 제시한다.&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-h3&quot;&gt;3단계 — 세션 재시작 (필수!)&lt;/div&gt;
    &lt;div class=&quot;bw-terminal&quot;&gt;
      &lt;div class=&quot;bw-term-bar&quot;&gt;
        &lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&lt;/div&gt;
        &lt;span class=&quot;bw-term-title&quot;&gt;Terminal&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-term-body&quot;&gt;
        &lt;div class=&quot;tm&quot;&gt;Claude Code 종료 후 재시작 — Skills는 세션 시작 시 로딩됨&lt;/div&gt;
        &lt;div class=&quot;tc&quot;&gt;claude&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-h3&quot;&gt;4단계 — Skill 호출&lt;/div&gt;
    &lt;div class=&quot;bw-terminal&quot;&gt;
      &lt;div class=&quot;bw-term-bar&quot;&gt;
        &lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&lt;/div&gt;
        &lt;span class=&quot;bw-term-title&quot;&gt;Claude Code&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-term-body&quot;&gt;
        &lt;div class=&quot;tp&quot;&gt;code-reviewer skill을 사용해서 @calculator.py 를 리뷰해줘&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;ts&quot;&gt;Skill(code-reviewer) — Successfully loaded skill&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;1. 타입 힌트 [심각도: 하] — 모든 함수 양호&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;2. Docstring [심각도: 중] — absolute 스타일 불일치&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;3. 예외 처리 [심각도: 중] — float == 0 비교 관행&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;4. Pythonic [심각도: 하] — math.pow → ** 권장&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;5. 로깅 [심각도: 하] — 전부 logger.debug() 사용 양호&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;hr class=&quot;bw-divider&quot;&gt;

  &lt;!-- STEP 4 --&gt;
  &lt;div class=&quot;bw-section&quot; id=&quot;s4&quot;&gt;
    &lt;div class=&quot;bw-section-header&quot;&gt;
      &lt;span class=&quot;bw-step-tag&quot;&gt;STEP 04&lt;/span&gt;
      &lt;h2 class=&quot;bw-section-title&quot;&gt;실수: &lt;span class=&quot;bw-st-orange&quot;&gt;Unknown skill 에러&lt;/span&gt;&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p class=&quot;bw-desc&quot;&gt;처음 Skill을 만들 때 거의 모두가 이 에러를 만납니다. 원인과 해결법을 정확히 알아두세요.&lt;/p&gt;

    &lt;div class=&quot;bw-terminal&quot;&gt;
      &lt;div class=&quot;bw-term-bar&quot;&gt;
        &lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&lt;/div&gt;
        &lt;span class=&quot;bw-term-title&quot;&gt;에러 상황&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-term-body&quot;&gt;
        &lt;div class=&quot;te&quot;&gt;Skill(code-reviewer)&lt;/div&gt;
        &lt;div class=&quot;te&quot;&gt;Error: Unknown skill: code-reviewer&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;tm&quot;&gt;리뷰는 됐지만 Skill은 로딩 안 됨 → 그냥 Claude가 직접 한 것&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-compare&quot;&gt;
      &lt;div class=&quot;bw-compare-card bw-cb&quot;&gt;
        &lt;span class=&quot;bw-compare-label&quot;&gt;❌ 흔한 실수&lt;/span&gt;
        &lt;span class=&quot;bw-compare-code&quot;&gt;Claude Code 세션 안에서만
파일 생성 후 바로 호출

or

세션 재시작 없이 호출&lt;/span&gt;
        &lt;span class=&quot;bw-compare-note&quot;&gt;→ Unknown skill 에러 발생&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-compare-card bw-cg&quot;&gt;
        &lt;span class=&quot;bw-compare-label&quot;&gt;✅ 올바른 순서&lt;/span&gt;
        &lt;span class=&quot;bw-compare-code&quot;&gt;1. mkdir -p .claude/skills/이름
2. SKILL.md 파일 생성
3. Claude Code 종료
4. claude 재시작
5. Skill 호출&lt;/span&gt;
        &lt;span class=&quot;bw-compare-note&quot;&gt;→ Successfully loaded skill ✓&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-callout bw-callout-warn&quot;&gt;
      &lt;span class=&quot;bw-callout-icon&quot;&gt;⚠️&lt;/span&gt;
      &lt;span class=&quot;bw-ct&quot;&gt;&lt;strong&gt;핵심:&lt;/strong&gt; Skills는 세션 시작 시 로딩됩니다. 파일을 직접 추가했다면 &lt;strong&gt;반드시 세션을 재시작&lt;/strong&gt;해야 합니다. 또는 &lt;span class=&quot;bw-code&quot;&gt;/agents&lt;/span&gt; 명령어로 즉시 로딩할 수도 있습니다.&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;hr class=&quot;bw-divider&quot;&gt;

  &lt;!-- STEP 5 --&gt;
  &lt;div class=&quot;bw-section&quot; id=&quot;s5&quot;&gt;
    &lt;div class=&quot;bw-section-header&quot;&gt;
      &lt;span class=&quot;bw-step-tag&quot;&gt;STEP 05&lt;/span&gt;
      &lt;h2 class=&quot;bw-section-title&quot;&gt;&lt;span class=&quot;bw-st-yellow&quot;&gt;병렬 에이전트&lt;/span&gt;란 무엇인가&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p class=&quot;bw-desc&quot;&gt;서브에이전트는 메인 세션이 특정 작업을 위해 생성하는 독립적인 Claude 인스턴스입니다. 각각 자신만의 200k 컨텍스트 창을 갖고 동시에 실행됩니다.&lt;/p&gt;

    &lt;div class=&quot;bw-parallel&quot;&gt;
      &lt;span class=&quot;bw-parallel-title&quot;&gt;순차 실행 vs 병렬 실행 비교&lt;/span&gt;
      &lt;div class=&quot;bw-parallel-row&quot;&gt;
        &lt;span class=&quot;bw-parallel-label&quot;&gt;순차 실행&lt;/span&gt;
        &lt;div class=&quot;bw-parallel-bars&quot;&gt;
          &lt;div class=&quot;bw-bar bw-bar-seq&quot; style=&quot;width:100% !important;&quot;&gt;Task A → Task B → Task C → Task D&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-parallel-row&quot;&gt;
        &lt;span class=&quot;bw-parallel-label&quot;&gt;병렬 실행&lt;/span&gt;
        &lt;div class=&quot;bw-parallel-bars&quot;&gt;
          &lt;div class=&quot;bw-bar bw-bar-par1&quot;&gt;Task A&lt;/div&gt;
          &lt;div class=&quot;bw-bar bw-bar-par2&quot;&gt;Task B&lt;/div&gt;
          &lt;div class=&quot;bw-bar bw-bar-par3&quot;&gt;Task C&lt;/div&gt;
          &lt;div class=&quot;bw-bar bw-bar-par4&quot;&gt;Task D&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;span class=&quot;bw-parallel-result&quot;&gt;동시 실행 → 최대 4배 빠름 · 각 에이전트 독립 200k 컨텍스트&lt;/span&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-h3&quot;&gt;언제 병렬 에이전트를 쓰나?&lt;/div&gt;
    &lt;table class=&quot;bw-table&quot;&gt;
      &lt;thead&gt;&lt;tr&gt;&lt;th&gt;상황&lt;/th&gt;&lt;th&gt;예시&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;대형 리팩토링&lt;/td&gt;&lt;td&gt;75개 파일의 함수명 변경 → 파일별 병렬 처리&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;멀티 서비스 분석&lt;/td&gt;&lt;td&gt;backend / frontend / infra 동시 분석&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;테스트 생성&lt;/td&gt;&lt;td&gt;각 모듈별 테스트 파일 병렬 작성&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;로그 분석&lt;/td&gt;&lt;td&gt;3개 마이크로서비스 로그 동시 분석 후 종합&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;코드 탐색&lt;/td&gt;&lt;td&gt;대형 코드베이스 디렉토리별 동시 탐색&lt;/td&gt;&lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;

  &lt;hr class=&quot;bw-divider&quot;&gt;

  &lt;!-- STEP 6 --&gt;
  &lt;div class=&quot;bw-section&quot; id=&quot;s6&quot;&gt;
    &lt;div class=&quot;bw-section-header&quot;&gt;
      &lt;span class=&quot;bw-step-tag&quot;&gt;STEP 06&lt;/span&gt;
      &lt;h2 class=&quot;bw-section-title&quot;&gt;병렬 실행 &lt;span class=&quot;bw-st-yellow&quot;&gt;직접 해보기&lt;/span&gt;&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p class=&quot;bw-desc&quot;&gt;Claude Code는 기본적으로 보수적으로 동작합니다. 병렬화를 최대화하려면 프롬프트에서 명시적으로 요청해야 합니다.&lt;/p&gt;

    &lt;div class=&quot;bw-h3&quot;&gt;핵심 — 명시적으로 요청하기&lt;/div&gt;

    &lt;div class=&quot;bw-compare&quot;&gt;
      &lt;div class=&quot;bw-compare-card bw-cb&quot;&gt;
        &lt;span class=&quot;bw-compare-label&quot;&gt;❌ 병렬 안 됨&lt;/span&gt;
        &lt;span class=&quot;bw-compare-code&quot;&gt;calculator.py 분석하고
테스트 커버리지도 확인하고
프로젝트 구조도 봐줘&lt;/span&gt;
        &lt;span class=&quot;bw-compare-note&quot;&gt;→ 순차적으로 하나씩 실행&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-compare-card bw-cg&quot;&gt;
        &lt;span class=&quot;bw-compare-label&quot;&gt;✅ 병렬 실행&lt;/span&gt;
        &lt;span class=&quot;bw-compare-code&quot;&gt;4개의 parallel 서브에이전트로
동시에 아래 작업을 해줘:
1. add/subtract 성능 분석
2. multiply/divide 성능 분석
3. 테스트 커버리지 분석
4. 프로젝트 구조 분석&lt;/span&gt;
        &lt;span class=&quot;bw-compare-note&quot;&gt;→ 4개 동시 실행&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-terminal&quot;&gt;
      &lt;div class=&quot;bw-term-bar&quot;&gt;
        &lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&lt;/div&gt;
        &lt;span class=&quot;bw-term-title&quot;&gt;Claude Code — 실제 실행 결과&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-term-body&quot;&gt;
        &lt;div class=&quot;ts&quot;&gt;4 agents launched&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;├─ Task (add/subtract 성능 분석)&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;│  ⎿  Running in the background&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;├─ Task (multiply/divide 성능 분석)&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;│  ⎿  Running in the background&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;├─ Task (테스트 커버리지 분석)&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;│  ⎿  Running in the background&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;└─ Explore (프로젝트 구조 분석)&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;   ⎿  Running in the background&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;tm&quot;&gt;30초 후...&lt;/div&gt;
        &lt;div class=&quot;ts&quot;&gt;Agent &quot;add/subtract 성능 분석&quot; completed&lt;/div&gt;
        &lt;div class=&quot;to&quot;&gt;→ 모든 에이전트 완료 후 메인 세션에서 결과 종합&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-callout bw-callout-tip&quot;&gt;
      &lt;span class=&quot;bw-callout-icon&quot;&gt; &lt;/span&gt;
      &lt;span class=&quot;bw-ct&quot;&gt;&quot;4개의 parallel 에이전트&quot;, &quot;동시에&quot; 같은 &lt;strong&gt;구체적인 숫자와 명시적 표현&lt;/strong&gt;이 핵심입니다. 모호하게 요청하면 Claude가 순차 실행을 선택합니다.&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;hr class=&quot;bw-divider&quot;&gt;

  &lt;!-- STEP 7 --&gt;
  &lt;div class=&quot;bw-section&quot; id=&quot;s7&quot;&gt;
    &lt;div class=&quot;bw-section-header&quot;&gt;
      &lt;span class=&quot;bw-step-tag&quot;&gt;STEP 07&lt;/span&gt;
      &lt;h2 class=&quot;bw-section-title&quot;&gt;&lt;span class=&quot;bw-st-purple&quot;&gt;Task vs Explore&lt;/span&gt; 에이전트&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p class=&quot;bw-desc&quot;&gt;병렬 실행 시 Claude가 자동으로 에이전트 유형을 선택합니다. 어떤 에이전트가 언제 선택되는지 알아두면 결과를 예측할 수 있습니다.&lt;/p&gt;

    &lt;div class=&quot;bw-agent-grid&quot;&gt;
      &lt;div class=&quot;bw-agent-card&quot;&gt;
        &lt;span class=&quot;bw-agent-name&quot;&gt;Task 에이전트&lt;/span&gt;
        &lt;span class=&quot;bw-agent-type at-task&quot;&gt;범용&lt;/span&gt;
        &lt;span class=&quot;bw-agent-desc&quot;&gt;파일 읽기·쓰기·수정 모두 가능. 성능 분석, 테스트 작성, 코드 수정 같은 &lt;strong&gt;실행이 필요한 작업&lt;/strong&gt;에 자동 선택됩니다.&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-agent-card&quot;&gt;
        &lt;span class=&quot;bw-agent-name&quot;&gt;Explore 에이전트&lt;/span&gt;
        &lt;span class=&quot;bw-agent-type at-explore&quot;&gt;읽기 전용&lt;/span&gt;
        &lt;span class=&quot;bw-agent-desc&quot;&gt;파일 읽기만 가능. 코드베이스 탐색, 구조 분석, 개선점 제안 같은 &lt;strong&gt;탐색·분석 작업&lt;/strong&gt;에 자동 선택됩니다.&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-terminal&quot;&gt;
      &lt;div class=&quot;bw-term-bar&quot;&gt;
        &lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&lt;/div&gt;&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&lt;/div&gt;
        &lt;span class=&quot;bw-term-title&quot;&gt;실제 실행에서 관찰된 패턴&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-term-body&quot;&gt;
        &lt;div class=&quot;tk&quot;&gt;├─ Task    (add/subtract 성능 분석)     ← 분석 + 결과 작성&lt;/div&gt;
        &lt;div class=&quot;tk&quot;&gt;├─ Task    (multiply/divide 성능 분석)  ← 분석 + 결과 작성&lt;/div&gt;
        &lt;div class=&quot;tk&quot;&gt;├─ Task    (테스트 커버리지 분석)        ← 파일 읽기 + 계산&lt;/div&gt;
        &lt;div class=&quot;tk&quot;&gt;└─ Explore (프로젝트 구조 분석)          ← 읽기 전용 탐색&lt;/div&gt;
        &lt;br&gt;
        &lt;div class=&quot;tm&quot;&gt;Claude가 작업 특성을 보고 자동으로 에이전트 유형 결정&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-callout bw-callout-info&quot;&gt;
      &lt;span class=&quot;bw-callout-icon&quot;&gt; &lt;/span&gt;
      &lt;span class=&quot;bw-ct&quot;&gt;빌트인 에이전트 외에 &lt;span class=&quot;bw-code&quot;&gt;.claude/agents/&lt;/span&gt; 폴더에 커스텀 에이전트를 만들 수 있습니다. 예: code-reviewer 에이전트, security-auditor 에이전트 등을 전용 도구 권한과 함께 정의할 수 있습니다.&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;hr class=&quot;bw-divider&quot;&gt;

  &lt;!-- STEP 8 --&gt;
  &lt;div class=&quot;bw-section&quot; id=&quot;s8&quot;&gt;
    &lt;div class=&quot;bw-section-header&quot;&gt;
      &lt;span class=&quot;bw-step-tag&quot;&gt;SUMMARY&lt;/span&gt;
      &lt;h2 class=&quot;bw-section-title&quot;&gt;1·2편 &lt;span class=&quot;bw-st-green&quot;&gt;전체 로드맵&lt;/span&gt; 총정리&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p class=&quot;bw-desc&quot;&gt;두 편에 걸쳐 배운 Claude Code의 핵심 기능 전체를 한눈에 정리합니다.&lt;/p&gt;

    &lt;div class=&quot;bw-roadmap&quot;&gt;
      &lt;div class=&quot;bw-roadmap-bar&quot;&gt;Claude Code 마스터 로드맵&lt;/div&gt;
      &lt;div class=&quot;bw-roadmap-body&quot;&gt;
        &lt;span class=&quot;rm-label&quot;&gt;# 1편 — 기초 정복&lt;/span&gt;
        &lt;span class=&quot;rm-done&quot;&gt;CLAUDE.md — 규칙을 한 번 쓰면 영원히 자동 적용&lt;/span&gt;
        &lt;span class=&quot;rm-done&quot;&gt;Plan Mode (Shift+Tab) — 실행 전 계획 검토&lt;/span&gt;
        &lt;span class=&quot;rm-done&quot;&gt;/clear — 새 작업마다 컨텍스트 초기화&lt;/span&gt;
        &lt;span class=&quot;rm-done&quot;&gt;@ 파일 참조 — 정확한 컨텍스트 타겟팅&lt;/span&gt;
        &lt;span class=&quot;rm-done&quot;&gt;프롬프트 패턴 — 역할+제약+검증 세트, TDD&lt;/span&gt;
        &lt;span class=&quot;rm-done&quot;&gt;Hooks — .claude/settings.json, Write|Edit|MultiEdit&lt;/span&gt;
        &lt;br&gt;
        &lt;span class=&quot;rm-label&quot;&gt;# 2편 — 고급 기능&lt;/span&gt;
        &lt;span class=&quot;rm-new&quot;&gt;Skills — .claude/skills/이름/SKILL.md 재사용 지식 패키지&lt;/span&gt;
        &lt;span class=&quot;rm-new&quot;&gt;병렬 에이전트 — &quot;N개의 parallel 에이전트로&quot; 명시적 요청&lt;/span&gt;
        &lt;br&gt;
        &lt;span class=&quot;rm-label&quot;&gt;# 다음 단계&lt;/span&gt;
        &lt;span class=&quot;rm-next&quot;&gt;MCP 서버 연동 — GitHub·DB 직접 연결&lt;/span&gt;
        &lt;span class=&quot;rm-next&quot;&gt;커스텀 서브에이전트 — .claude/agents/ 전문가 팀 구성&lt;/span&gt;
        &lt;span class=&quot;rm-next&quot;&gt;CI/CD 파이프라인 통합&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;bw-summary-grid&quot;&gt;
      &lt;div class=&quot;bw-summary-card&quot;&gt;
        &lt;span class=&quot;bw-sc-icon&quot;&gt; &lt;/span&gt;
        &lt;span class=&quot;bw-sc-title&quot;&gt;Skills = 재사용 지식&lt;/span&gt;
        &lt;span class=&quot;bw-sc-desc&quot;&gt;반복하는 작업을 SKILL.md로 정의. 폴더명이 이름. 세션 재시작 필수.&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-summary-card&quot;&gt;
        &lt;span class=&quot;bw-sc-icon&quot;&gt;⚡&lt;/span&gt;
        &lt;span class=&quot;bw-sc-title&quot;&gt;병렬 = 명시적 요청&lt;/span&gt;
        &lt;span class=&quot;bw-sc-desc&quot;&gt;&quot;N개의 parallel 에이전트로 동시에&quot; — 구체적 숫자와 명시적 표현 필수.&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-summary-card&quot;&gt;
        &lt;span class=&quot;bw-sc-icon&quot;&gt; &lt;/span&gt;
        &lt;span class=&quot;bw-sc-title&quot;&gt;Task vs Explore&lt;/span&gt;
        &lt;span class=&quot;bw-sc-desc&quot;&gt;실행 작업 → Task 자동 선택. 탐색 분석 → Explore 자동 선택.&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;bw-summary-card&quot;&gt;
        &lt;span class=&quot;bw-sc-icon&quot;&gt; &lt;/span&gt;
        &lt;span class=&quot;bw-sc-title&quot;&gt;저장 위치 원칙&lt;/span&gt;
        &lt;span class=&quot;bw-sc-desc&quot;&gt;Skills·Hooks·Agents 모두 프로젝트 레벨 .claude/에 저장. 전역 ~/.claude/는 최소화.&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- FOOTER --&gt;
  &lt;div class=&quot;bw-footer&quot;&gt;
    &lt;p class=&quot;bw-footer-text&quot;&gt;
      Claude Code 실전 튜터리얼 2편 · macOS + Claude Pro 환경 기준&lt;br&gt;
      공식 문서: &lt;span class=&quot;bw-footer-link&quot;&gt;docs.anthropic.com/en/docs/claude-code&lt;/span&gt;
    &lt;/p&gt;
  &lt;/div&gt;

&lt;/div&gt;</description>
      <category>Claude</category>
      <category>Code</category>
      <category>skill</category>
      <category>skill.md</category>
      <category>subagent</category>
      <category>병렬실행</category>
      <category>스킬</category>
      <category>코드</category>
      <category>클로드</category>
      <category>튜터리얼</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/238</guid>
      <comments>https://windflex.tistory.com/238#entry238comment</comments>
      <pubDate>Fri, 20 Feb 2026 00:16:44 +0900</pubDate>
    </item>
    <item>
      <title>  Claude Code Tutorial - 1 (클로드 코드 튜터리얼)</title>
      <link>https://windflex.tistory.com/237</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJS7ab/dJMcagdsVDP/P2TBZTlQUsAqEQwxrf6x21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJS7ab/dJMcagdsVDP/P2TBZTlQUsAqEQwxrf6x21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJS7ab/dJMcagdsVDP/P2TBZTlQUsAqEQwxrf6x21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJS7ab%2FdJMcagdsVDP%2FP2TBZTlQUsAqEQwxrf6x21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;
&lt;style&gt;
  .blog-wrap,
  .blog-wrap *,
  .blog-wrap *::before,
  .blog-wrap *::after {
    box-sizing: border-box !important;
  }

  .blog-wrap {
    background: #f8f7f4 !important;
    color: #1a1814 !important;
    max-width: 780px !important;
    margin: 0 auto !important;
    padding: 0 !important;
    line-height: 1.8 !important;
    font-family: 'Pretendard', -apple-system, sans-serif !important;
  }

  /* ===== HERO ===== */
  .bw-hero {
    background: linear-gradient(160deg, #1e1a38 0%, #2a1f50 50%, #1a2040 100%) !important;
    padding: 80px 40px 70px !important;
    text-align: center !important;
    border-radius: 16px !important;
    margin-bottom: 56px !important;
    position: relative !important;
    overflow: hidden !important;
  }

  .bw-badge {
    display: inline-block !important;
    background: rgba(255,255,255,0.1) !important;
    border: 1px solid rgba(255,255,255,0.2) !important;
    border-radius: 100px !important;
    padding: 5px 16px !important;
    font-size: 12px !important;
    color: #c8c0ff !important;
    letter-spacing: 0.06em !important;
    margin-bottom: 28px !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-hero-title {
    font-family: 'Noto Serif KR', serif !important;
    font-size: 2.4rem !important;
    font-weight: 700 !important;
    color: #ffffff !important;
    line-height: 1.25 !important;
    margin: 0 0 20px !important;
  }

  .bw-ht-orange { color: #ffb366 !important; }
  .bw-ht-purple { color: #b8b0ff !important; }

  .bw-hero-sub {
    font-size: 1.05rem !important;
    color: rgba(255,255,255,0.6) !important;
    margin: 0 auto 40px !important;
    max-width: 500px !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-stats {
    display: flex !important;
    justify-content: center !important;
    gap: 48px !important;
  }

  .bw-stat-num {
    display: block !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 2rem !important;
    font-weight: 600 !important;
    color: #ffb366 !important;
    line-height: 1 !important;
    margin-bottom: 4px !important;
  }

  .bw-stat-label {
    display: block !important;
    font-size: 11px !important;
    color: rgba(255,255,255,0.4) !important;
    letter-spacing: 0.1em !important;
    text-transform: uppercase !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  /* ===== TOC ===== */
  .bw-toc {
    background: #f0ede8 !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 12px !important;
    padding: 24px 28px !important;
    margin-bottom: 56px !important;
  }

  .bw-toc-title {
    font-size: 11px !important;
    font-weight: 600 !important;
    letter-spacing: 0.12em !important;
    text-transform: uppercase !important;
    color: #8a8480 !important;
    margin: 0 0 16px !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-toc-list {
    list-style: none !important;
    padding: 0 !important;
    margin: 0 !important;
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 6px !important;
  }

  .bw-toc-item {
    margin: 0 !important;
    padding: 0 !important;
    list-style: none !important;
  }

  .bw-toc-link {
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
    font-size: 0.9rem !important;
    color: #4a4540 !important;
    text-decoration: none !important;
    padding: 5px 0 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-toc-num {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    color: #c4500a !important;
    background: rgba(196,80,10,0.1) !important;
    border-radius: 4px !important;
    padding: 2px 6px !important;
    flex-shrink: 0 !important;
  }

  /* ===== SECTION ===== */
  .bw-section {
    margin-bottom: 72px !important;
  }

  .bw-section-header {
    display: flex !important;
    align-items: flex-start !important;
    gap: 16px !important;
    margin-bottom: 20px !important;
    padding-bottom: 18px !important;
    border-bottom: 2px solid #e8e4dd !important;
  }

  .bw-step-tag {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    font-weight: 600 !important;
    letter-spacing: 0.08em !important;
    color: #c4500a !important;
    background: rgba(196,80,10,0.08) !important;
    border: 1px solid rgba(196,80,10,0.2) !important;
    border-radius: 6px !important;
    padding: 4px 10px !important;
    white-space: nowrap !important;
    margin-top: 6px !important;
    flex-shrink: 0 !important;
  }

  .bw-section-title {
    font-family: 'Noto Serif KR', serif !important;
    font-size: 1.55rem !important;
    font-weight: 700 !important;
    color: #1a1814 !important;
    line-height: 1.3 !important;
    margin: 0 !important;
  }

  .bw-st-orange { color: #c4500a !important; }
  .bw-st-purple { color: #4a3fb5 !important; }
  .bw-st-green  { color: #1a7a42 !important; }

  .bw-desc {
    font-size: 1.02rem !important;
    color: #4a4540 !important;
    margin: 0 0 20px !important;
    line-height: 1.75 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-p {
    color: #1a1814 !important;
    margin: 0 0 14px !important;
    font-size: 1rem !important;
    line-height: 1.8 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-h3 {
    font-size: 1.02rem !important;
    font-weight: 700 !important;
    color: #1a1814 !important;
    margin: 24px 0 10px !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  /* ===== TERMINAL ===== */
  .bw-terminal {
    background: #1e1c18 !important;
    border-radius: 12px !important;
    overflow: hidden !important;
    margin: 18px 0 !important;
    box-shadow: 0 4px 20px rgba(0,0,0,0.15) !important;
  }

  .bw-term-bar {
    display: flex !important;
    align-items: center !important;
    gap: 7px !important;
    padding: 10px 16px !important;
    background: #2a2820 !important;
    border-bottom: 1px solid #3a3830 !important;
  }

  .bw-dot {
    width: 11px !important;
    height: 11px !important;
    border-radius: 50% !important;
    flex-shrink: 0 !important;
    display: inline-block !important;
  }

  .bw-dot-r { background: #ff5f57 !important; }
  .bw-dot-y { background: #febc2e !important; }
  .bw-dot-g { background: #28c840 !important; }

  .bw-term-title {
    flex: 1 !important;
    text-align: center !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    color: #7a7060 !important;
  }

  .bw-term-body {
    padding: 18px 22px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 13px !important;
    line-height: 1.8 !important;
    color: #e0dbd0 !important;
  }

  .tc { color: #4ecf8a !important; display: block !important; }
  .tc::before { content: '$ ' !important; color: #5a5040 !important; }
  .tp { color: #9b8fff !important; display: block !important; }
  .tp::before { content: '&gt; ' !important; color: #5a5040 !important; }
  .to { color: #a09880 !important; display: block !important; }
  .ts { color: #4ecf8a !important; display: block !important; }
  .ts::before { content: '✓ ' !important; }
  .tm { color: #5a5040 !important; display: block !important; }
  .tm::before { content: '# ' !important; }

  /* ===== INLINE CODE ===== */
  .bw-code {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 0.87em !important;
    background: #ede9e2 !important;
    border: 1px solid #d0ccc4 !important;
    border-radius: 5px !important;
    padding: 2px 7px !important;
    color: #c4500a !important;
  }

  /* ===== CALLOUT ===== */
  .bw-callout {
    display: flex !important;
    gap: 12px !important;
    align-items: flex-start !important;
    border-radius: 10px !important;
    padding: 14px 18px !important;
    margin: 16px 0 !important;
    font-size: 0.93rem !important;
    line-height: 1.7 !important;
  }

  .bw-callout-tip  { background: #edf7f1 !important; border: 1px solid #b8e0c8 !important; }
  .bw-callout-warn { background: #fef8ec !important; border: 1px solid #f5dc90 !important; }
  .bw-callout-info { background: #eef0fb !important; border: 1px solid #b8bef0 !important; }

  .bw-callout-icon { font-size: 1.05rem !important; flex-shrink: 0 !important; margin-top: 1px !important; }

  .bw-callout-tip  .bw-ct { color: #1a5c34 !important; font-family: 'Pretendard', sans-serif !important; }
  .bw-callout-warn .bw-ct { color: #6b4c00 !important; font-family: 'Pretendard', sans-serif !important; }
  .bw-callout-info .bw-ct { color: #2a3090 !important; font-family: 'Pretendard', sans-serif !important; }

  /* ===== RESULT BOX ===== */
  .bw-result {
    background: #f0ede8 !important;
    border: 1px solid #d8d3cb !important;
    border-left: 4px solid #1a7a42 !important;
    border-radius: 0 10px 10px 0 !important;
    padding: 16px 20px !important;
    margin: 16px 0 !important;
  }

  .bw-result-label {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.1em !important;
    text-transform: uppercase !important;
    color: #1a7a42 !important;
    margin-bottom: 10px !important;
    display: block !important;
  }

  .bw-result-body {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 12.5px !important;
    color: #4a4540 !important;
    line-height: 1.75 !important;
  }

  .rb-g { color: #1a7a42 !important; font-weight: 600 !important; }

  /* ===== COMPARE ===== */
  .bw-compare {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 14px !important;
    margin: 18px 0 !important;
  }

  .bw-compare-card { border-radius: 10px !important; padding: 18px !important; }
  .bw-cb { background: #fdf0f0 !important; border: 1px solid #f0c0c0 !important; }
  .bw-cg { background: #f0f8f3 !important; border: 1px solid #a8dbb8 !important; }

  .bw-compare-label {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.1em !important;
    text-transform: uppercase !important;
    margin-bottom: 10px !important;
    display: block !important;
  }

  .bw-cb .bw-compare-label { color: #c03030 !important; }
  .bw-cg .bw-compare-label { color: #1a7a42 !important; }

  .bw-compare-code {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 12px !important;
    color: #4a4540 !important;
    line-height: 1.65 !important;
    white-space: pre-line !important;
    display: block !important;
  }

  .bw-compare-note {
    font-size: 11.5px !important;
    margin-top: 10px !important;
    padding-top: 10px !important;
    border-top: 1px solid rgba(0,0,0,0.08) !important;
    font-family: 'Pretendard', sans-serif !important;
    display: block !important;
  }

  .bw-cb .bw-compare-note { color: #c03030 !important; }
  .bw-cg .bw-compare-note { color: #1a7a42 !important; }

  /* ===== TABLE ===== */
  .bw-table {
    width: 100% !important;
    border-collapse: collapse !important;
    margin: 16px 0 !important;
    font-size: 0.92rem !important;
  }

  .bw-table th {
    text-align: left !important;
    padding: 9px 16px !important;
    background: #e8e4dd !important;
    color: #4a4540 !important;
    font-weight: 600 !important;
    font-size: 11px !important;
    letter-spacing: 0.06em !important;
    text-transform: uppercase !important;
    border-bottom: 2px solid #d0ccc4 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-table td {
    padding: 10px 16px !important;
    border-bottom: 1px solid #e8e4dd !important;
    color: #4a4540 !important;
    vertical-align: top !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-table td:first-child {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 12px !important;
    color: #4a3fb5 !important;
    white-space: nowrap !important;
  }

  .bw-table tr:last-child td { border-bottom: none !important; }

  /* ===== SUMMARY CARDS ===== */
  .bw-summary-grid {
    display: grid !important;
    grid-template-columns: repeat(3, 1fr) !important;
    gap: 12px !important;
    margin: 24px 0 !important;
  }

  .bw-summary-card {
    background: #f0ede8 !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 12px !important;
    padding: 16px !important;
  }

  .bw-sc-icon {
    font-size: 1.3rem !important;
    margin-bottom: 8px !important;
    display: block !important;
  }

  .bw-sc-title {
    font-weight: 700 !important;
    font-size: 0.9rem !important;
    color: #1a1814 !important;
    margin-bottom: 4px !important;
    display: block !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-sc-desc {
    font-size: 0.81rem !important;
    color: #6a6460 !important;
    line-height: 1.5 !important;
    display: block !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  /* ===== WORKFLOW ===== */
  .bw-flow {
    background: #1e1c18 !important;
    border-radius: 12px !important;
    overflow: hidden !important;
    margin: 18px 0 !important;
    box-shadow: 0 4px 20px rgba(0,0,0,0.15) !important;
  }

  .bw-flow-bar {
    background: #2a2820 !important;
    border-bottom: 1px solid #3a3830 !important;
    padding: 10px 16px !important;
    display: flex !important;
    align-items: center !important;
    gap: 7px !important;
  }

  .bw-flow-title {
    flex: 1 !important;
    text-align: center !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    color: #7a7060 !important;
  }

  .bw-flow-body {
    padding: 20px 24px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 13px !important;
    line-height: 1.9 !important;
    color: #e0dbd0 !important;
  }

  .fw-note { color: #5a5040 !important; display: block !important; }
  .fw-note::before { content: '# ' !important; }
  .fw-cmd  { color: #4ecf8a !important; display: block !important; }
  .fw-cmd::before { content: '$ ' !important; color: #5a5040 !important; }
  .fw-tip  { color: #9b8fff !important; display: block !important; }
  .fw-tip::before { content: '&gt; ' !important; color: #5a5040 !important; }
  .fw-out  { color: #a09880 !important; display: block !important; }

  /* ===== DIVIDER ===== */
  .bw-divider {
    height: 1px !important;
    background: linear-gradient(to right, transparent, #d8d3cb, transparent) !important;
    margin: 56px 0 !important;
    border: none !important;
  }

  /* ===== FOOTER ===== */
  .bw-footer {
    background: #f0ede8 !important;
    border: 1px solid #d8d3cb !important;
    border-radius: 12px !important;
    padding: 26px !important;
    text-align: center !important;
    margin-top: 48px !important;
  }

  .bw-footer-text {
    color: #8a8480 !important;
    font-size: 0.875rem !important;
    margin: 0 !important;
    line-height: 1.7 !important;
    font-family: 'Pretendard', sans-serif !important;
  }

  .bw-footer-link { color: #4a3fb5 !important; }

  @media (max-width: 600px) {
    .bw-hero { padding: 48px 20px 40px !important; }
    .bw-hero-title { font-size: 1.7rem !important; }
    .bw-stats { gap: 24px !important; }
    .bw-compare { grid-template-columns: 1fr !important; }
    .bw-summary-grid { grid-template-columns: 1fr 1fr !important; }
    .bw-toc-list { grid-template-columns: 1fr !important; }
  }
&lt;/style&gt;
&lt;/div&gt;
&lt;div class=&quot;blog-wrap&quot;&gt;&lt;!-- HERO --&gt;
&lt;div class=&quot;bw-hero&quot;&gt;
&lt;div class=&quot;bw-badge&quot;&gt;  실전 튜터리얼&lt;/div&gt;
&lt;h1 class=&quot;bw-hero-title&quot;&gt;&lt;span class=&quot;bw-ht-orange&quot;&gt;Claude Code&lt;/span&gt;를&lt;br /&gt;&lt;span class=&quot;bw-ht-purple&quot;&gt;정교하게&lt;/span&gt; 사용하는 법&lt;/h1&gt;
&lt;p class=&quot;bw-hero-sub&quot; data-ke-size=&quot;size16&quot;&gt;설치부터 Hooks 자동화까지 &amp;mdash; 직접 따라하며 배우는 Step-by-Step 가이드&lt;/p&gt;
&lt;div class=&quot;bw-stats&quot;&gt;
&lt;div&gt;&lt;span class=&quot;bw-stat-num&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;bw-stat-label&quot;&gt;핵심 단계&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot;bw-stat-num&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;bw-stat-label&quot;&gt;테스트 통과&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&quot;bw-stat-num&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;bw-stat-label&quot;&gt;사전 지식 필요&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- TOC --&gt;
&lt;div class=&quot;bw-toc&quot;&gt;
&lt;div class=&quot;bw-toc-title&quot;&gt;목차&lt;/div&gt;
&lt;ul class=&quot;bw-toc-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a class=&quot;bw-toc-link&quot; href=&quot;#s0&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;00&lt;/span&gt; 환경 준비&lt;/a&gt;&lt;/li&gt;
&lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a class=&quot;bw-toc-link&quot; href=&quot;#s1&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;01&lt;/span&gt; CLAUDE.md&lt;/a&gt;&lt;/li&gt;
&lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a class=&quot;bw-toc-link&quot; href=&quot;#s2&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;02&lt;/span&gt; Plan Mode&lt;/a&gt;&lt;/li&gt;
&lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a class=&quot;bw-toc-link&quot; href=&quot;#s3&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;03&lt;/span&gt; 슬래시 명령어&lt;/a&gt;&lt;/li&gt;
&lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a class=&quot;bw-toc-link&quot; href=&quot;#s4&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;04&lt;/span&gt; @ 파일 참조&lt;/a&gt;&lt;/li&gt;
&lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a class=&quot;bw-toc-link&quot; href=&quot;#s5&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;05&lt;/span&gt; 프롬프트 패턴&lt;/a&gt;&lt;/li&gt;
&lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a class=&quot;bw-toc-link&quot; href=&quot;#s6&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;06&lt;/span&gt; Hooks 자동화&lt;/a&gt;&lt;/li&gt;
&lt;li class=&quot;bw-toc-item&quot;&gt;&lt;a class=&quot;bw-toc-link&quot; href=&quot;#s7&quot;&gt;&lt;span class=&quot;bw-toc-num&quot;&gt;07&lt;/span&gt; 워크플로우 총정리&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!-- STEP 0 --&gt;
&lt;div id=&quot;s0&quot; class=&quot;bw-section&quot;&gt;
&lt;div class=&quot;bw-section-header&quot;&gt;&lt;span class=&quot;bw-step-tag&quot;&gt;STEP 00&lt;/span&gt;
&lt;h2 class=&quot;bw-section-title&quot; data-ke-size=&quot;size26&quot;&gt;시작 전 &lt;span class=&quot;bw-st-orange&quot;&gt;환경 확인&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-desc&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code는 터미널에서 실행되는 도구입니다. claude.ai 채팅창이 아닙니다.&lt;/p&gt;
&lt;p class=&quot;bw-p&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Node.js 18 이상이 설치되어 있는지 확인하세요:&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Terminal&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tc&quot;&gt;node --version&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;v25.3.0 &amp;nbsp;&amp;larr; v18 이상이면 OK&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;tm&quot;&gt;Claude Code 설치 (이미 설치된 경우 생략)&lt;/div&gt;
&lt;div class=&quot;tc&quot;&gt;npm install -g @anthropic-ai/claude-code&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;tm&quot;&gt;연습 프로젝트 폴더 생성 후 시작&lt;/div&gt;
&lt;div class=&quot;tc&quot;&gt;mkdir claude-tutorial &amp;amp;&amp;amp; cd claude-tutorial &amp;amp;&amp;amp; claude&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-callout bw-callout-info&quot;&gt;&lt;span class=&quot;bw-callout-icon&quot;&gt;ℹ️&lt;/span&gt; &lt;span class=&quot;bw-ct&quot;&gt;&lt;b&gt;필요 조건:&lt;/b&gt; macOS/Linux/WSL 터미널 + Claude Pro($20/월) 이상 구독 또는 Anthropic API 키.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr class=&quot;bw-divider&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;!-- STEP 1 --&gt;
&lt;div id=&quot;s1&quot; class=&quot;bw-section&quot;&gt;
&lt;div class=&quot;bw-section-header&quot;&gt;&lt;span class=&quot;bw-step-tag&quot;&gt;STEP 01&lt;/span&gt;
&lt;h2 class=&quot;bw-section-title&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span class=&quot;bw-st-orange&quot;&gt;CLAUDE.md&lt;/span&gt; &amp;mdash; 한 번 쓰고 영원히 적용&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-desc&quot; data-ke-size=&quot;size16&quot;&gt;가장 중요한 기능입니다. Claude Code가 프로젝트 시작 시 자동으로 읽는 규칙 파일입니다. 여기에 코딩 규칙을 써두면 매번 설명할 필요가 없어집니다.&lt;/p&gt;
&lt;p class=&quot;bw-p&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code 세션 안에서 &lt;span class=&quot;bw-code&quot;&gt;/init&lt;/span&gt; 명령어로 CLAUDE.md를 자동 생성합니다:&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Claude Code&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tp&quot;&gt;/init&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;CLAUDE.md를 생성할까요? &amp;rarr; Yes 선택&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-p&quot; data-ke-size=&quot;size16&quot;&gt;그 다음 실제 규칙을 직접 작성합니다:&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Claude Code&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tp&quot;&gt;CLAUDE.md를 아래 내용으로 업데이트해줘:&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;to&quot;&gt;- 언어: Python&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;- 코딩 스타일: 함수마다 docstring 필수, 타입 힌트 사용&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;- 테스트: 새 함수 만들면 pytest 테스트도 항상 같이 작성&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;- 커밋 메시지: 한국어로 작성&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;- 절대 하지 말 것: print 대신 logging, 전역변수 금지&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-callout bw-callout-tip&quot;&gt;&lt;span class=&quot;bw-callout-icon&quot;&gt; &lt;/span&gt; &lt;span class=&quot;bw-ct&quot;&gt;&lt;b&gt;왜 강력한가?&lt;/b&gt; 이 파일이 있으면 앞으로 이 프로젝트에서 Claude Code를 열 때마다 자동으로 규칙을 따릅니다. &quot;타입 힌트 써줘&quot;, &quot;테스트도 작성해줘&quot;를 매번 말하지 않아도 됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-callout bw-callout-warn&quot;&gt;&lt;span class=&quot;bw-callout-icon&quot;&gt;⚠️&lt;/span&gt; &lt;span class=&quot;bw-ct&quot;&gt;CLAUDE.md는 &lt;b&gt;git에 커밋&lt;/b&gt;해두면 팀원 모두가 같은 규칙을 공유할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr class=&quot;bw-divider&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;!-- STEP 2 --&gt;
&lt;div id=&quot;s2&quot; class=&quot;bw-section&quot;&gt;
&lt;div class=&quot;bw-section-header&quot;&gt;&lt;span class=&quot;bw-step-tag&quot;&gt;STEP 02&lt;/span&gt;
&lt;h2 class=&quot;bw-section-title&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span class=&quot;bw-st-purple&quot;&gt;Plan Mode&lt;/span&gt; &amp;mdash; 실행 전 계획 검토&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-desc&quot; data-ke-size=&quot;size16&quot;&gt;Claude가 파일을 건드리기 전에 &quot;이렇게 할 계획입니다&quot;를 먼저 보여주는 모드입니다. 큰 작업 전에 방향이 맞는지 확인할 수 있어서 필수입니다.&lt;/p&gt;
&lt;div class=&quot;bw-h3&quot;&gt;Plan Mode 진입&lt;/div&gt;
&lt;p class=&quot;bw-p&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code 세션에서 &lt;b&gt;Shift + Tab&lt;/b&gt;을 누르면 모드가 순환합니다:&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;모드 전환 &amp;mdash; Shift + Tab&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;to&quot;&gt;Normal &amp;rarr; Auto-Accept &amp;rarr; Plan Mode &amp;rarr; Normal &amp;rarr; ...&lt;/div&gt;
&lt;div class=&quot;tm&quot;&gt;왼쪽 하단에 현재 모드 표시됨&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-p&quot; data-ke-size=&quot;size16&quot;&gt;Plan Mode로 전환 후 아래를 입력해보세요:&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Claude Code &amp;mdash; Plan Mode&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tp&quot;&gt;간단한 계산기 Python 파일을 만들어줘.&lt;/div&gt;
&lt;div class=&quot;tp&quot;&gt;더하기, 빼기, 곱하기, 나누기 기능 포함.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-result&quot;&gt;&lt;span class=&quot;bw-result-label&quot;&gt;실제 Plan Mode 출력 결과&lt;/span&gt;
&lt;div class=&quot;bw-result-body&quot;&gt;생성할 파일: calculator.py&lt;br /&gt;&amp;mdash; add(a, b), subtract(a, b), multiply(a, b), divide(a, b)&lt;br /&gt;&amp;mdash; divide는 0으로 나눌 때 ValueError 발생&lt;br /&gt;&amp;mdash; 모든 함수에 docstring + 타입 힌트 &lt;span class=&quot;rb-g&quot;&gt;&amp;larr; CLAUDE.md 규칙 자동 적용!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;test_calculator.py&lt;br /&gt;&amp;mdash; 각 연산 함수에 대한 pytest 테스트 케이스 &lt;span class=&quot;rb-g&quot;&gt;&amp;larr; 자동 포함!&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-callout bw-callout-tip&quot;&gt;&lt;span class=&quot;bw-callout-icon&quot;&gt; &lt;/span&gt; &lt;span class=&quot;bw-ct&quot;&gt;CLAUDE.md에 써둔 규칙들을 Claude가 스스로 읽고 계획에 반영했습니다. 계획이 마음에 들면 &lt;b&gt;승인&lt;/b&gt;, 아니면 수정 요청 후 승인할 수 있습니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr class=&quot;bw-divider&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;!-- STEP 3 --&gt;
&lt;div id=&quot;s3&quot; class=&quot;bw-section&quot;&gt;
&lt;div class=&quot;bw-section-header&quot;&gt;&lt;span class=&quot;bw-step-tag&quot;&gt;STEP 03&lt;/span&gt;
&lt;h2 class=&quot;bw-section-title&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span class=&quot;bw-st-orange&quot;&gt;슬래시 명령어&lt;/span&gt; 마스터&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-desc&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code 세션 안에서 바로 사용할 수 있는 핵심 명령어들입니다.&lt;/p&gt;
&lt;table class=&quot;bw-table&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;명령어&lt;/th&gt;
&lt;th&gt;기능&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;/init&lt;/td&gt;
&lt;td&gt;프로젝트 분석 후 CLAUDE.md 자동 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/clear&lt;/td&gt;
&lt;td&gt;대화 히스토리 초기화 (파일은 그대로 유지)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/plan&lt;/td&gt;
&lt;td&gt;Plan Mode 진입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/doctor&lt;/td&gt;
&lt;td&gt;설치 및 환경 진단&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;bw-h3&quot;&gt;/clear &amp;mdash; 가장 중요한 습관&lt;/div&gt;
&lt;p class=&quot;bw-p&quot; data-ke-size=&quot;size16&quot;&gt;새 작업을 시작할 때마다 &lt;span class=&quot;bw-code&quot;&gt;/clear&lt;/span&gt;를 실행하세요. 대화 히스토리가 길어지면 토큰이 낭비되고 Claude가 혼선을 일으킵니다. 파일 자체는 그대로 남습니다.&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Claude Code&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tp&quot;&gt;/clear&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;대화 초기화됨&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;tp&quot;&gt;calculator.py가 뭐 하는 파일이야?&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;ts&quot;&gt;파일을 직접 읽어서 정확하게 답변&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;대화 히스토리가 없어도 실제 파일을 읽기 때문에 정확히 동작&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr class=&quot;bw-divider&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;!-- STEP 4 --&gt;
&lt;div id=&quot;s4&quot; class=&quot;bw-section&quot;&gt;
&lt;div class=&quot;bw-section-header&quot;&gt;&lt;span class=&quot;bw-step-tag&quot;&gt;STEP 04&lt;/span&gt;
&lt;h2 class=&quot;bw-section-title&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span class=&quot;bw-st-purple&quot;&gt;@ 파일 참조&lt;/span&gt; &amp;mdash; 정확한 컨텍스트&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-desc&quot; data-ke-size=&quot;size16&quot;&gt;여러 파일이 있을 때 Claude가 어떤 파일을 봐야 하는지 명시적으로 지정합니다. 프로젝트가 커질수록 엉뚱한 파일을 수정하는 실수를 방지하는 핵심 기능입니다.&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Claude Code&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tp&quot;&gt;@test_calculator.py 를 보고,&lt;/div&gt;
&lt;div class=&quot;tp&quot;&gt;테스트가 빠진 엣지케이스가 있으면 추가해줘&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;ts&quot;&gt;11개 &amp;rarr; 22개 테스트로 자동 확장&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;- add: 0 더하기, 양수+음수 혼합&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;- subtract: 0 빼기, 같은 수 빼기, 부동소수점&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;- divide: 음수&amp;divide;음수, 0&amp;divide;숫자, &amp;divide;1(항등원)&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-callout bw-callout-tip&quot;&gt;&lt;span class=&quot;bw-callout-icon&quot;&gt; &lt;/span&gt; &lt;span class=&quot;bw-ct&quot;&gt;파일명 타이핑 중에 &lt;b&gt;Tab 자동완성&lt;/b&gt;이 됩니다. 여러 파일 동시 참조도 가능합니다: &lt;span class=&quot;bw-code&quot;&gt;@calculator.py @test_calculator.py&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr class=&quot;bw-divider&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;!-- STEP 5 --&gt;
&lt;div id=&quot;s5&quot; class=&quot;bw-section&quot;&gt;
&lt;div class=&quot;bw-section-header&quot;&gt;&lt;span class=&quot;bw-step-tag&quot;&gt;STEP 05&lt;/span&gt;
&lt;h2 class=&quot;bw-section-title&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span class=&quot;bw-st-green&quot;&gt;프롬프트 패턴&lt;/span&gt; &amp;mdash; 되묻기 없애기&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-desc&quot; data-ke-size=&quot;size16&quot;&gt;같은 요청도 어떻게 쓰느냐에 따라 결과가 완전히 달라집니다. 가장 실전적인 부분입니다.&lt;/p&gt;
&lt;div class=&quot;bw-compare&quot;&gt;
&lt;div class=&quot;bw-compare-card bw-cb&quot;&gt;&lt;span class=&quot;bw-compare-label&quot;&gt;❌ 나쁜 프롬프트&lt;/span&gt; &lt;span class=&quot;bw-compare-code&quot;&gt;calculator에 기능 추가해줘&lt;/span&gt; &lt;span class=&quot;bw-compare-note&quot;&gt;&amp;rarr; &quot;어떤 기능을 추가할까요?&quot; 되물음&lt;br /&gt;작업 중단, 계속 기다려야 함&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-compare-card bw-cg&quot;&gt;&lt;span class=&quot;bw-compare-label&quot;&gt;✅ 좋은 프롬프트&lt;/span&gt; &lt;span class=&quot;bw-compare-code&quot;&gt;@calculator.py 에 추가: - power(base, exp): 거듭제곱 - sqrt(a): 제곱근 제약: 기존 함수 건드리지 말 것 테스트도 추가 후 pytest 실행&lt;/span&gt; &lt;span class=&quot;bw-compare-note&quot;&gt;&amp;rarr; 코드 + 테스트 + 검증 한 번에 완료&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-h3&quot;&gt;패턴 1: 역할 + 제약 + 검증 세트&lt;/div&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Claude Code&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tp&quot;&gt;@calculator.py 를 시니어 Python 개발자 관점에서 리뷰해줘.&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;to&quot;&gt;리뷰 항목: 타입 힌트 누락 / 예외 처리 미흡 / Pythonic하지 않은 코드&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;출력 형식: [심각도: 상/중/하] 표시&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;수정은 하지 말고 리뷰만 해줘&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-h3&quot;&gt;패턴 2: TDD (테스트 먼저 작성)&lt;/div&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Claude Code &amp;mdash; TDD 방식&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tp&quot;&gt;modulo(a, b) 함수를 추가할건데,&lt;/div&gt;
&lt;div class=&quot;tp&quot;&gt;코드 작성 전에 실패하는 테스트를 먼저 @test_calculator.py 에 작성해줘.&lt;/div&gt;
&lt;div class=&quot;tp&quot;&gt;테스트 실패 확인 후에 구현해줘.&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;to&quot;&gt;1. 테스트 작성 &amp;rarr; ImportError 확인 (Red  )&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;2. 함수 구현&lt;/div&gt;
&lt;div class=&quot;ts&quot;&gt;3. 37/37 테스트 PASSED (Green  )&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-callout bw-callout-info&quot;&gt;&lt;span class=&quot;bw-callout-icon&quot;&gt; &lt;/span&gt; &lt;span class=&quot;bw-ct&quot;&gt;TDD는 실무에서 가장 안전한 개발 방식입니다. Red(실패) &amp;rarr; Green(통과) 순서를 Claude가 그대로 따릅니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr class=&quot;bw-divider&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;!-- STEP 6 --&gt;
&lt;div id=&quot;s6&quot; class=&quot;bw-section&quot;&gt;
&lt;div class=&quot;bw-section-header&quot;&gt;&lt;span class=&quot;bw-step-tag&quot;&gt;STEP 06&lt;/span&gt;
&lt;h2 class=&quot;bw-section-title&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span class=&quot;bw-st-orange&quot;&gt;Hooks&lt;/span&gt; &amp;mdash; 자동화 트리거&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-desc&quot; data-ke-size=&quot;size16&quot;&gt;특정 이벤트가 발생할 때 자동으로 셸 명령을 실행합니다. 파일 저장 시 자동 테스트 실행이 대표적입니다.&lt;/p&gt;
&lt;div class=&quot;bw-h3&quot;&gt;이벤트 종류&lt;/div&gt;
&lt;table class=&quot;bw-table&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;이벤트&lt;/th&gt;
&lt;th&gt;발생 시점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PreToolUse&lt;/td&gt;
&lt;td&gt;Claude가 도구 사용하기 직전&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PostToolUse&lt;/td&gt;
&lt;td&gt;Claude가 도구 사용한 직후 &amp;larr; 가장 많이 씀&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stop&lt;/td&gt;
&lt;td&gt;Claude가 응답 완료했을 때&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;bw-h3&quot;&gt;⚠️ 저장 위치가 핵심!&lt;/div&gt;
&lt;table class=&quot;bw-table&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;파일 위치&lt;/th&gt;
&lt;th&gt;범위&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;~/.claude/settings.json&lt;/td&gt;
&lt;td&gt;전역 &amp;mdash; 모든 프로젝트에 적용 (비추천)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.claude/settings.json&lt;/td&gt;
&lt;td&gt;✅ 프로젝트 &amp;mdash; 이 프로젝트에만 적용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.claude/settings.local.json&lt;/td&gt;
&lt;td&gt;로컬 &amp;mdash; git 제외 개인 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p class=&quot;bw-p&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트별로 다른 테스트 파일이 있으므로 반드시 &lt;b&gt;프로젝트 레벨&lt;/b&gt;에 저장해야 합니다.&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;Claude Code&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;tp&quot;&gt;PostToolUse hook을 설정해줘.&lt;/div&gt;
&lt;div class=&quot;tp&quot;&gt;조건: Write|Edit|MultiEdit 도구로 .py 파일 저장 시&lt;/div&gt;
&lt;div class=&quot;tp&quot;&gt;동작: python3 -m pytest test_calculator.py -q 자동 실행&lt;/div&gt;
&lt;div class=&quot;tp&quot;&gt;전역(~/.claude)이 아닌 프로젝트(.claude)에 저장해줘.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-p&quot; data-ke-size=&quot;size16&quot;&gt;생성되는 &lt;span class=&quot;bw-code&quot;&gt;.claude/settings.json&lt;/span&gt; 구조:&lt;/p&gt;
&lt;div class=&quot;bw-terminal&quot;&gt;
&lt;div class=&quot;bw-term-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-term-title&quot;&gt;.claude/settings.json&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-term-body&quot;&gt;
&lt;div class=&quot;to&quot;&gt;{&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;&amp;nbsp;&amp;nbsp;&quot;hooks&quot;: {&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;PostToolUse&quot;: [{&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;matcher&quot;: &lt;span style=&quot;color: #4ecf8a !important;&quot;&gt;&quot;Write|Edit|MultiEdit&quot;&lt;/span&gt;,&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;hooks&quot;: [{ &quot;type&quot;: &quot;command&quot;,&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;command&quot;: &quot;python3 -m pytest test_calculator.py -q&quot; }]&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}]&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;
&lt;div class=&quot;to&quot;&gt;}&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-callout bw-callout-warn&quot;&gt;&lt;span class=&quot;bw-callout-icon&quot;&gt;⚠️&lt;/span&gt; &lt;span class=&quot;bw-ct&quot;&gt;matcher를 &lt;span class=&quot;bw-code&quot;&gt;Write&lt;/span&gt;만 설정하면 &lt;b&gt;Edit 도구로 수정할 때 트리거가 안 됩니다.&lt;/b&gt; 반드시 &lt;span class=&quot;bw-code&quot;&gt;Write|Edit|MultiEdit&lt;/span&gt; 세 가지를 모두 포함하세요.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr class=&quot;bw-divider&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;!-- SUMMARY --&gt;
&lt;div id=&quot;s7&quot; class=&quot;bw-section&quot;&gt;
&lt;div class=&quot;bw-section-header&quot;&gt;&lt;span class=&quot;bw-step-tag&quot;&gt;SUMMARY&lt;/span&gt;
&lt;h2 class=&quot;bw-section-title&quot; data-ke-size=&quot;size26&quot;&gt;실전 &lt;span class=&quot;bw-st-purple&quot;&gt;워크플로우&lt;/span&gt; 총정리&lt;/h2&gt;
&lt;/div&gt;
&lt;p class=&quot;bw-desc&quot; data-ke-size=&quot;size16&quot;&gt;오늘 배운 것들을 실전에서 사용하는 순서로 정리했습니다.&lt;/p&gt;
&lt;div class=&quot;bw-flow&quot;&gt;
&lt;div class=&quot;bw-flow-bar&quot;&gt;
&lt;div class=&quot;bw-dot bw-dot-r&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-y&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bw-dot bw-dot-g&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;span class=&quot;bw-flow-title&quot;&gt;최적 워크플로우&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-flow-body&quot;&gt;
&lt;div class=&quot;fw-note&quot;&gt;1. 새 프로젝트 시작&lt;/div&gt;
&lt;div class=&quot;fw-cmd&quot;&gt;mkdir my-project &amp;amp;&amp;amp; cd my-project &amp;amp;&amp;amp; claude&lt;/div&gt;
&lt;div class=&quot;fw-tip&quot;&gt;/init &amp;rarr; CLAUDE.md에 언어&amp;middot;스타일&amp;middot;금지사항 작성&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;fw-note&quot;&gt;2. 큰 작업 전&lt;/div&gt;
&lt;div class=&quot;fw-out&quot;&gt;Shift+Tab (Plan Mode) &amp;rarr; 계획 검토 &amp;rarr; 승인&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;fw-note&quot;&gt;3. 작업 시&lt;/div&gt;
&lt;div class=&quot;fw-tip&quot;&gt;@파일명 + 요구사항 + 제약 + 검증 세트로 작성&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;fw-note&quot;&gt;4. 새 작업마다&lt;/div&gt;
&lt;div class=&quot;fw-tip&quot;&gt;/clear &amp;rarr; 컨텍스트 초기화&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;fw-note&quot;&gt;5. 자동화&lt;/div&gt;
&lt;div class=&quot;fw-out&quot;&gt;.claude/settings.json &amp;rarr; PostToolUse Hook 설정&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;bw-summary-grid&quot;&gt;
&lt;div class=&quot;bw-summary-card&quot;&gt;&lt;span class=&quot;bw-sc-icon&quot;&gt; &lt;/span&gt; &lt;span class=&quot;bw-sc-title&quot;&gt;CLAUDE.md&lt;/span&gt; &lt;span class=&quot;bw-sc-desc&quot;&gt;규칙을 한 번만 써두면 영원히 자동 적용&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-summary-card&quot;&gt;&lt;span class=&quot;bw-sc-icon&quot;&gt; &lt;/span&gt; &lt;span class=&quot;bw-sc-title&quot;&gt;Plan Mode&lt;/span&gt; &lt;span class=&quot;bw-sc-desc&quot;&gt;Shift+Tab &amp;mdash; 실행 전 검토, 큰 작업 필수&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-summary-card&quot;&gt;&lt;span class=&quot;bw-sc-icon&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;bw-sc-title&quot;&gt;파일 참조&lt;/span&gt; &lt;span class=&quot;bw-sc-desc&quot;&gt;정확한 컨텍스트로 엉뚱한 수정 방지&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-summary-card&quot;&gt;&lt;span class=&quot;bw-sc-icon&quot;&gt;✍️&lt;/span&gt; &lt;span class=&quot;bw-sc-title&quot;&gt;프롬프트 패턴&lt;/span&gt; &lt;span class=&quot;bw-sc-desc&quot;&gt;역할+제약+검증 세트로 되묻기 없앰&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-summary-card&quot;&gt;&lt;span class=&quot;bw-sc-icon&quot;&gt; &lt;/span&gt; &lt;span class=&quot;bw-sc-title&quot;&gt;Hooks&lt;/span&gt; &lt;span class=&quot;bw-sc-desc&quot;&gt;프로젝트 레벨 .claude/settings.json에만 저장&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;bw-summary-card&quot;&gt;&lt;span class=&quot;bw-sc-icon&quot;&gt; &lt;/span&gt; &lt;span class=&quot;bw-sc-title&quot;&gt;/clear 습관&lt;/span&gt; &lt;span class=&quot;bw-sc-desc&quot;&gt;새 작업마다 컨텍스트 초기화 필수&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- FOOTER --&gt;
&lt;div class=&quot;bw-footer&quot;&gt;
&lt;p class=&quot;bw-footer-text&quot; data-ke-size=&quot;size16&quot;&gt;Claude Code 실전 튜터리얼 &amp;middot; macOS + Claude Pro 환경 기준&lt;br /&gt;공식 문서: &lt;span class=&quot;bw-footer-link&quot;&gt;docs.anthropic.com/en/docs/claude-code&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Claude</category>
      <category>Claude.md</category>
      <category>Code</category>
      <category>Hook</category>
      <category>Plan Mode</category>
      <category>Settings</category>
      <category>슬래시</category>
      <category>코드</category>
      <category>클로드</category>
      <category>튜터리얼</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/237</guid>
      <comments>https://windflex.tistory.com/237#entry237comment</comments>
      <pubDate>Thu, 19 Feb 2026 23:19:43 +0900</pubDate>
    </item>
    <item>
      <title>맥북 샀어? 그럼 터미널부터 꾸며야지! Zsh &amp;amp; Warp 완벽 가이드  </title>
      <link>https://windflex.tistory.com/236</link>
      <description>&lt;h1&gt;  맥북 샀어? 그럼 터미널부터 꾸며야지! Zsh &amp;amp; Warp 완벽 가이드&lt;/h1&gt;
&lt;p&gt;새 맥북을 구매하신 모든 분들, 축하드립니다!  &lt;br&gt;맥북을 샀다면 가장 먼저 해야 할 일, 바로 개발자의 &amp;#39;집&amp;#39;과 같은 &lt;strong&gt;터미널 세팅&lt;/strong&gt;이죠.&lt;br&gt;검정 화면에 하얀 글자만 나오는 기본 터미널은 이제 안녕! 효율을 200% 올려주는 세팅법을 쉽고 캐주얼하게 알려드릴게요.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;1. 터미널의 국룰, Oh My Zsh 설치하기  &lt;/h2&gt;
&lt;p&gt;맥북은 기본적으로 &lt;code&gt;Zsh&lt;/code&gt;를 사용하지만, 그냥 쓰면 너무 밋밋하죠.&lt;br&gt;그래서 우리는 &lt;strong&gt;Oh My Zsh&lt;/strong&gt;라는 프레임워크를 설치해서 터미널에 예쁜 옷을 입히고 똑똑한 기능을 추가할 거예요.&lt;/p&gt;
&lt;h3&gt;✨ 왜 쓰나요?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;가독성:&lt;/strong&gt; 현재 내가 어떤 폴더에 있는지, Git 브랜치는 무엇인지 한눈에 보여요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;편의성:&lt;/strong&gt; 명령어 자동 완성, 오타 강조 등 강력한 플러그인을 쓸 수 있어요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dSXGZd/dJMcachyhtO/eIaQrtdKZwT34BwAHUArSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dSXGZd/dJMcachyhtO/eIaQrtdKZwT34BwAHUArSk/img.png&quot; data-alt=&quot;Oh My Zsh 설치 및 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dSXGZd/dJMcachyhtO/eIaQrtdKZwT34BwAHUArSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdSXGZd%2FdJMcachyhtO%2FeIaQrtdKZwT34BwAHUArSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1378&quot; height=&quot;514&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Oh My Zsh 설치 및 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;  설치 방법&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Homebrew 설치&lt;/strong&gt; (맥북 필수 패키지 관리자):&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/bin/bash -c &amp;quot;$(curl -fsSL [https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh](https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh))&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;2. **Oh My Zsh 설치**:
```bash
sh -c &amp;quot;$(curl -fsSL [https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh](https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh))&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;  추천 테마: Powerlevel10k&lt;/strong&gt; &amp;gt; 가장 인기 있는 테마예요. 설치 과정에서 질문에 답만 하면 나만의 터미널 디자인이 완성됩니다!&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;p&gt;블로그에 기술적인 내용을 보충하기 위해 &lt;strong&gt;Oh My Zsh와 Powerlevel10k를 설정하는 상세 단계&lt;/strong&gt;를 정리해 드립니다. 이 내용을 블로그의 중간 섹션에 추가하거나 별도의 &amp;#39;심화 가이드&amp;#39;로 활용하시면 좋습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;  Oh My Zsh &amp;amp; Powerlevel10k 상세 설정 가이드&lt;/h2&gt;
&lt;p&gt;단순히 설치하는 것을 넘어, 터미널을 정말 &amp;quot;쓸만하게&amp;quot; 만드는 핵심 과정입니다.&lt;/p&gt;
&lt;h3&gt;1. 폰트 설치 (가장 중요! ⭐)&lt;/h3&gt;
&lt;p&gt;Powerlevel10k는 화살표나 아이콘을 많이 사용합니다. 일반 폰트를 쓰면 아이콘이 깨져서 보이므로 &lt;strong&gt;Nerd Font&lt;/strong&gt;가 필수입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;가장 추천하는 폰트: &lt;strong&gt;MesloLGS NF&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;설정 방법:&lt;/strong&gt; iTerm2 설정(&lt;code&gt;Cmd + ,&lt;/code&gt;) &amp;gt; Profiles &amp;gt; Text &amp;gt; Font에서 &amp;#39;MesloLGS NF&amp;#39;로 변경하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Powerlevel10k 설치하기&lt;/h3&gt;
&lt;p&gt;터미널에서 아래 명령어를 복사해서 실행하세요.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;3. 테마 적용하기&lt;/h3&gt;
&lt;p&gt;설정 파일(&lt;code&gt;.zshrc&lt;/code&gt;)을 열어 테마 이름을 변경해야 합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;vi ~/.zshrc&lt;/code&gt; 또는 &lt;code&gt;open -e ~/.zshrc&lt;/code&gt; 명령어로 파일을 엽니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ZSH_THEME=&amp;quot;robbyrussell&amp;quot;&lt;/code&gt; 부분을 찾아 아래와 같이 수정합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ZSH_THEME=&amp;quot;powerlevel10k/powerlevel10k&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;저장 후 터미널을 재시작하거나 &lt;code&gt;source ~/.zshrc&lt;/code&gt;를 입력합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;4. 인터랙티브 설정 (Wizard)&lt;/h3&gt;
&lt;p&gt;터미널을 다시 열면 자동으로 &lt;strong&gt;설정 마법사&lt;/strong&gt;가 시작됩니다. 만약 안 뜬다면 &lt;code&gt;p10k configure&lt;/code&gt;를 입력하세요.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;다이아몬드가 보이나요?&amp;quot;, &amp;quot;잠금 아이콘이 보이나요?&amp;quot; 등의 질문에 &lt;code&gt;y&lt;/code&gt; 혹은 &lt;code&gt;n&lt;/code&gt;으로 답하면서 본인의 취향대로 터미널 디자인을 커스터마이징할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;  생산성을 높여주는 필수 플러그인 설정&lt;/h2&gt;
&lt;p&gt;터미널에서 명령어를 일일이 치지 않아도 되게 만들어주는 설정입니다.&lt;/p&gt;
&lt;h3&gt;① 플러그인 다운로드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 자동 완성 플러그인
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

# 문법 강조 플러그인
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;② &lt;code&gt;.zshrc&lt;/code&gt; 파일에 등록&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;.zshrc&lt;/code&gt; 파일에서 &lt;code&gt;plugins=(git)&lt;/code&gt; 부분을 찾아 아래와 같이 수정합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;plugins=(
  git
  zsh-autosuggestions
  zsh-syntax-highlighting
)&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;2. 터미널의 혁명, Warp가 왜 필요할까? ⚡️&lt;/h2&gt;
&lt;p&gt;전통적인 방식이 iTerm2 + Oh My Zsh라면, 요즘 뜨는 &amp;#39;터미널 계의 테슬라&amp;#39;는 바로 &lt;strong&gt;Warp(워프)&lt;/strong&gt;입니다.&lt;/p&gt;
&lt;h3&gt;  Warp를 써야 하는 이유 (Necessity)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AI가 내장되어 있어요:&lt;/strong&gt; 명령어가 기억 안 날 때 &lt;code&gt;#&lt;/code&gt;만 치고 &amp;quot;최근 커밋 취소해줘&amp;quot;라고 물어보세요. AI가 바로 답을 줍니다.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;블록(Block) 단위 UI:&lt;/strong&gt; 명령어와 결과값이 하나의 박스로 묶여 있어 가독성이 끝내주고, 특정 결과만 복사하기 정말 편해요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;속도가 미쳤어요:&lt;/strong&gt; Rust 기반이라 엄청나게 빠르고 부드럽습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;마우스 클릭 가능:&lt;/strong&gt; 터미널 커서를 마우스로 툭 찍어서 이동할 수 있다는 게 얼마나 편한지 써보시면 압니다!&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1314&quot; data-origin-height=&quot;874&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfIVKc/dJMcacaNGKc/7q5mkKtKYlreTkbaTGuvLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfIVKc/dJMcacaNGKc/7q5mkKtKYlreTkbaTGuvLK/img.png&quot; data-alt=&quot;warp 화면 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfIVKc/dJMcacaNGKc/7q5mkKtKYlreTkbaTGuvLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfIVKc%2FdJMcacaNGKc%2F7q5mkKtKYlreTkbaTGuvLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1314&quot; height=&quot;874&quot; data-origin-width=&quot;1314&quot; data-origin-height=&quot;874&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;warp 화면 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2&gt;3. Warp 설치 및 설정하기  ️&lt;/h2&gt;
&lt;p&gt;Warp는 복잡한 설정 파일을 만질 필요가 거의 없어서 초보자에게 더 추천드려요.&lt;/p&gt;
&lt;h3&gt;✅ 설치하기&lt;/h3&gt;
&lt;p&gt;터미널에서 아래 한 줄만 입력하면 끝!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew install --cask warp&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;✅ 초기 설정 팁&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Appearance:&lt;/strong&gt; &lt;code&gt;Settings &amp;gt; Appearance&lt;/code&gt;에서 테마를 바꿔보세요. 다크 모드가 정말 세련됐습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI Command Search:&lt;/strong&gt; 궁금한 게 생기면 무조건 &lt;code&gt;#&lt;/code&gt; 키를 누르고 질문해 보세요. 구글링 시간이 절반으로 줄어듭니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;4. 한눈에 비교: Zsh vs Warp ⚖️&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;특징&lt;/th&gt;
&lt;th&gt;Oh My Zsh (Classic)&lt;/th&gt;
&lt;th&gt;Warp (Modern)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;설정 난이도&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;조금 복잡 (설정 파일 수정)&lt;/td&gt;
&lt;td&gt;매우 쉬움 (설치 후 바로 사용)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;디자인&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;내가 직접 커스텀하는 맛&lt;/td&gt;
&lt;td&gt;세련된 기본 UI + 테마&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;주요 기능&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;무궁무진한 플러그인 생태계&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AI 통합&lt;/strong&gt;, 블록 단위 UI, 워크플로우&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;추천 대상&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;튜닝 끝판왕을 원하는 분&lt;/td&gt;
&lt;td&gt;설정 귀찮고 똑똑한 도구가 좋은 분&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;마치며 ✍️&lt;/h2&gt;
&lt;p&gt;새 맥북과 함께하는 코딩 라이프, 어떤 터미널로 시작하고 싶으신가요?&lt;br&gt;내 입맛대로 하나하나 꾸미는 재미는 &lt;strong&gt;Oh My Zsh&lt;/strong&gt;가, 압도적인 편리함과 AI의 도움은 &lt;strong&gt;Warp&lt;/strong&gt;가 앞섭니다.&lt;/p&gt;
&lt;p&gt;사실 정답은 없어요! 둘 다 설치해 보고 나에게 맞는 &amp;#39;인생 터미널&amp;#39;을 찾아보세요.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;도움이 되셨다면 공감과 댓글 부탁드려요!&lt;/strong&gt; 궁금한 점은 언제든 물어봐 주세요.  &lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>Homebrew 설치</category>
      <category>iTerm2</category>
      <category>oh my zsh</category>
      <category>Powerlevel101</category>
      <category>Warp 터미널</category>
      <category>개발자 맥북 세팅</category>
      <category>맥북 초기 설정</category>
      <category>터미널 ai</category>
      <category>터미널 꾸미기</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/236</guid>
      <comments>https://windflex.tistory.com/236#entry236comment</comments>
      <pubDate>Sat, 17 Jan 2026 18:23:09 +0900</pubDate>
    </item>
    <item>
      <title>2025년 글로벌 경제 동향 분석: Fed 정책과 시장 전망</title>
      <link>https://windflex.tistory.com/235</link>
      <description>&lt;h1&gt;2025년 글로벌 경제 동향 분석&lt;/h1&gt;
&lt;h2&gt;1. 연방준비제도(Fed) 통화정책 동향&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Fed는 최근 회의에서 신중한 입장을 유지하고 있으나, 시장은 여전히 불안정한 모습&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;올해 인플레이션 전망치를 3%로 상향 조정&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Powell 의장은 관세 정책이 소비자 물가 상승에 &amp;#39;의미 있는&amp;#39; 영향을 미칠 것으로 전망&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. 글로벌 IPO 시장 침체&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;글로벌 주식 IPO 규모가 9년 만에 최저치 기록&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;전년 대비 9.3% 감소한 443억 달러 수준&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;관세 분쟁과 시장 변동성이 주요 원인으로 지목&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. 미국 달러 강세와 원유가 상승&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;달러 강세와 유가 상승이 동시에 발생하며 글로벌 주식시장에 부담&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;이러한 조합은 시장의 불안정성을 가중시키는 요인으로 작용&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;특히 신흥국 시장에 대한 우려가 증가&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. 이란-이스라엘 갈등 영향&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;지정학적 리스크가 시장 불확실성 증가의 주요 요인으로 부각&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;중동 지역 긴장 고조로 인한 에너지 가격 변동성 확대&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;글로벌 금융시장의 안전자산 선호 현상 강화&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5. 글로벌 무역 긴장 고조&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;무역 분쟁 우려가 다시 부각되며 시장 불확실성 확대&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;스위스 등 주요 교역국들의 무역 전망에 대한 우려 증가&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;관세 리스크가 인플레이션 압력으로 작용할 가능성 제기&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;참고 자료&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.investing.com/news/economy/iranisrael-conflict-fed-decision-powell-on-inflation--whats-moving-markets-4102558&quot;&gt;Fed 통화정책과 인플레이션 분석&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.investing.com/news/stock-market-news/global-ipo-volumes-drop-to-9year-low-amid-tariffs-and-volatility-93CH-4102736&quot;&gt;글로벌 IPO 시장 동향&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.investing.com/analysis/us-dollar-strength-and-oil-surge-a-fragile-mix-for-global-equities-200662486&quot;&gt;달러 강세와 원유가 영향 분석&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/235</guid>
      <comments>https://windflex.tistory.com/235#entry235comment</comments>
      <pubDate>Thu, 19 Jun 2025 22:36:52 +0900</pubDate>
    </item>
    <item>
      <title>2025년 6월 부동산/경제 동향 종합 보고서</title>
      <link>https://windflex.tistory.com/234</link>
      <description>&lt;h1&gt;2025년 6월 부동산/경제 종합 보고서&lt;/h1&gt;
&lt;h2&gt;1. 부동산 시장 동향&lt;/h2&gt;
&lt;p&gt;최근 서울을 중심으로 한 부동산 시장이 강세를 보이고 있습니다. 특히 강남 3구를 중심으로 한 상승세가 두드러지며, 이는 공급 부족과 향후 금리 인하 기대감이 복합적으로 작용한 결과로 분석됩니다. 다만 전문가들은 무리한 추격 매수에 대해서는 주의를 당부하고 있습니다.  &lt;/p&gt;
&lt;h2&gt;2. 산업용 부동산 시장 현황&lt;/h2&gt;
&lt;p&gt;산업용 부동산 시장은 경기 침체의 직격탄을 맞았습니다. 공장 및 창고 거래량이 20% 가량 감소하며, 전반적인 산업용 부동산 시장이 어려움을 겪고 있는 것으로 나타났습니다. 이는 전반적인 경기 둔화와 관련이 있는 것으로 분석됩니다.  &lt;/p&gt;
&lt;h2&gt;3. 정부 정책 동향&lt;/h2&gt;
&lt;p&gt;현 정부는 &amp;#39;세금으로 집값을 잡지 않겠다&amp;#39;는 기조를 유지하고 있으며, 시장 친화적인 정책을 추진할 것으로 예상됩니다. 이러한 정책 기조는 부동산 시장에 긍정적인 시그널로 작용할 것으로 전망됩니다.  &lt;/p&gt;
&lt;h2&gt;4. 제로에너지 인증 의무화 정책&lt;/h2&gt;
&lt;p&gt;민간 아파트에 대한 제로에너지 인증 의무화 정책이 시행될 예정입니다. 이는 장기적으로 연료비 절감 효과가 있을 것으로 기대되나, 단기적으로는 분양가 상승 요인으로 작용할 수 있어 시장의 주목을 받고 있습니다.  &lt;/p&gt;
&lt;h2&gt;5. 거시경제 환경&lt;/h2&gt;
&lt;p&gt;한국은행은 현재 국내 의식주 물가가 OECD 평균을 크게 웃도는 것으로 분석하고 있으며, 이는 소비 제약 요인으로 작용할 수 있다고 경고하고 있습니다. 또한 시티그룹은 서울 아파트 가격이 연간 10% 이상 상승할 것으로 전망하고 있으며, 이로 인해 금리 인하 시기가 지연될 수 있다고 분석하고 있습니다.  &lt;/p&gt;
&lt;h2&gt;참고자료&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.joongang.co.kr/article/25344825&quot;&gt;중앙일보 - 부동산 시장 동향&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.joongang.co.kr/article/25343091&quot;&gt;중앙일보 - 산업용 부동산&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.mk.co.kr/news/economy/11347281&quot;&gt;매일경제 - 정부 정책&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.karnews.or.kr/&quot;&gt;한국자동차신문 - 제로에너지&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://mk.co.kr/estate/news//436978&quot;&gt;매일경제 - 거시경제&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/234</guid>
      <comments>https://windflex.tistory.com/234#entry234comment</comments>
      <pubDate>Thu, 19 Jun 2025 22:28:33 +0900</pubDate>
    </item>
    <item>
      <title>2025년 여름 휴가 트렌드: 새로운 여행의 패러다임과 추천 여행지</title>
      <link>https://windflex.tistory.com/233</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, 여행 애호가 여러분!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년 여름이 다가오면서 여행의 패러다임이 크게 변화하고 있습니다. 코로나19 이후 완전히 달라진 여행 문화와 새로운 기술의 발전, 그리고 변화하는 소비자들의 니즈가 만나 전혀 새로운 여행 트렌드가 형성되고 있죠. 오늘은 2025년 여름 휴가 시즌의 주요 트렌드와 이에 맞춘 추천 여행지를 상세히 알아보도록 하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 2025년 주목해야 할 여행 트렌드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) 경험 중심의 여행 (Experience-focused Travel)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순 관광이 아닌 현지 문화 체험 선호&lt;/li&gt;
&lt;li&gt;쿠킹 클래스, 예술 워크샵 등 참여형 활동 증가&lt;/li&gt;
&lt;li&gt;현지인과의 교류를 중시하는 프로그램 인기&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) 스마트 버짓 여행 (Smart Budget Travel)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI 기반 가격 비교 및 최적 예약 시기 활용&lt;/li&gt;
&lt;li&gt;공유 경제 서비스 활용 증가&lt;/li&gt;
&lt;li&gt;장기체류형 워케이션으로 비용 효율화&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) 웰니스 &amp;amp; 힐링 여행 (Wellness Travel)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정신적, 육체적 건강을 위한 여행 수요 증가&lt;/li&gt;
&lt;li&gt;요가 리트릿, 명상 프로그램 인기&lt;/li&gt;
&lt;li&gt;자연 친화적인 에코 리조트 선호&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) 쿨케이션 (Coolcation)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;폭염을 피해 시원한 지역으로 떠나는 여행&lt;/li&gt;
&lt;li&gt;북유럽, 고산지대 인기&lt;/li&gt;
&lt;li&gt;실내 액티비티가 가능한 목적지 선호&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 2025년 추천 여행지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) 국내 추천지&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;강원도 평창: 시원한 기후와 웰니스 시설 완비&lt;/li&gt;
&lt;li&gt;제주 서귀포: AI 기반 스마트 관광 시스템 도입&lt;/li&gt;
&lt;li&gt;울릉도: 독특한 섬 문화 체험과 시원한 해양성 기후&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) 해외 추천지&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일본 홋카이도: 시원한 기후와 온천 힐링&lt;/li&gt;
&lt;li&gt;이탈리아 트리에스테: 숨은 유럽 관광지의 매력&lt;/li&gt;
&lt;li&gt;태국 치앙마이: 현지 문화 체험과 웰니스 프로그램&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년의 여행은 단순한 관광이 아닌, 개인의 성장과 힐링, 그리고 의미 있는 경험을 추구하는 방향으로 진화하고 있습니다. 여러분도 이러한 트렌드를 참고하여 자신만의 특별한 여름 휴가를 계획해보시는 건 어떨까요?&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;World Travel Trends Report 2025&lt;/li&gt;
&lt;li&gt;한국관광공사 '2025 관광트렌드 분석'&lt;/li&gt;
&lt;li&gt;Global Tourism Insights 2025&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>나의 이야기/사회 및 생활</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/233</guid>
      <comments>https://windflex.tistory.com/233#entry233comment</comments>
      <pubDate>Thu, 19 Jun 2025 12:37:19 +0900</pubDate>
    </item>
    <item>
      <title>2025년 디지털 혁신의 물결: AI와 데이터가 이끄는 미래 기술 트렌드 전망</title>
      <link>https://windflex.tistory.com/232</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;서론: 디지털 혁신의 새로운 지평&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론: 2025년을 향한 디지털 혁신의 시급성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년을 앞두고 있는 지금, 기업들은 디지털 혁신의 큰 길목에 서 있습니다. AI와 데이터 기술의 발전은 산업 전반에 걸쳐 혁신적인 변화를 촉발하고 있으며, 이러한 변화에 적응하지 못하는 기업은 도태될 수밖에 없는 현실입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 주목해야 할 부분은 다음과 같습니다:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. AI와 데이터 기술의 실질적 활용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 디지털 인재 역량 강화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 조직 문화의 혁신적 변화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행동 계획(Call-to-Action):&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 디지털 역량 진단 및 평가 실시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 단계별 디지털 혁신 로드맵 수립&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 혁신 역량 강화를 위한 교육 프로그램 개발&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 더 이상 디지털 혁신은 선택이 아닌 필수가 되었습니다. 2025년을 향한 준비는 지금 시작되어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고자료:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. CES 2025 Technology Trends Report&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Capgemini Digital Transformation Review 2024&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. SK C&amp;amp;C Digital Innovation Insight 2025&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Samsung SDS Tech Navigator 2025&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 기술 트렌드를 성공적으로 도입하기 위해서는 체계적인 접근이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 디지털 역량 투자 및 강화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 인재 교육 및 역량 개발 프로그램 운영&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- AI와 데이터 분석 역량 확보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 디지털 인프라 구축 및 혁신&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 조직 문화 혁신&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 데이터 기반 의사결정 문화 정착&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실험과 혁신을 장려하는 조직 문화 조성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 변화 관리와 직원 인게이지먼트 강화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 파트너십 및 생태계 구축&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 전략적 파트너십 구축&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 스타트업과의 협력 강화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 산업 간 협력 모델 개발&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;산업별 영향과 전망&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 제조업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- AI 기반 스마트 팩토리 확대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실시간 생산 모니터링 및 예측 유지보수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 공급체인 디지털화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 금융업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- AI 기반 위험 분석 및 자산 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 개인화된 금융 서비스 확대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 블록체인 기술 활용 확대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 소매업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자 행동 분석 기반 개인화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 오프라인-온라인 통합 경험 강화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- AI 기반 재고 관리 및 수요 예측&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 2025년을 주도할 주요 기술 트렌드와 디지털 혁신의 방향성을 심도 있게 살펴보고, 기업들이 이러한 변화에 어떻게 대응해야 하는지 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 기술 트렌드 및 전망&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. AI 기반 자동화의 고도화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 인공지능 기술의 실용적 적용 확대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 로봇공학과 AI의 융합으로 인한 생산성 혁신&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기업 의사결정 프로세스의 AI 도입 가속화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 데이터 중심 경영의 진화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실시간 데이터 분석 및 활용 증가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 데이터 사일로 제거를 통한 통합적 데이터 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 엔터프라이즈 데이터의 전략적 가치 창출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 클라우드 전환 가속화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 하이브리드/멀티 클라우드 환경 보편화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클라우드 네이티브 애플리케이션 개발 증가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클라우드 기반 협업 도구의 고도화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 사용자 중심 디지털 경험&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 개인화된 서비스 제공 확대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- AI 기반 고객 경험 최적화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 초연결 환경에서의 원활한 서비스 제공&lt;/p&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/232</guid>
      <comments>https://windflex.tistory.com/232#entry232comment</comments>
      <pubDate>Thu, 19 Jun 2025 12:33:02 +0900</pubDate>
    </item>
    <item>
      <title>2024년 주목해야 할 인공지능(AI) 기술 트렌드 5가지</title>
      <link>https://windflex.tistory.com/231</link>
      <description>&lt;p&gt;인공지능 기술은 하루가 다르게 발전하고 있습니다. 2024년을 맞이하여 주목해야 할 AI 기술 트렌드를 살펴보고, 이러한 변화가 우리의 일상과 비즈니스에 어떤 영향을 미칠지 알아보겠습니다.&lt;/p&gt;
&lt;h2&gt;1. 생성형 AI의 진화&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;더욱 정교해진 텍스트, 이미지, 음성 생성 능력&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;산업 특화된 맞춤형 AI 모델의 등장&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;윤리적 고려사항과 저작권 문제 해결 노력&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. AI 기반 자동화의 가속화&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;비즈니스 프로세스의 전면적 자동화&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;로봇 프로세스 자동화(RPA)와 AI의 결합&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;업무 효율성과 생산성의 획기적 향상&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. 엣지 AI의 부상&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;실시간 데이터 처리와 즉각적인 의사결정&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;개인정보 보호 강화&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IoT 기기와의 seamless한 통합&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. 설명 가능한 AI(XAI)의 중요성 증가&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;AI 의사결정 과정의 투명성 확보&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;규제 준수와 신뢰성 향상&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;금융, 의료 등 중요 산업에서의 필수 요소&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5. AI와 인간의 협업 모델 발전&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;AI 보조 도구를 활용한 창의적 작업&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;교육과 학습에서의 AI 활용&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;새로운 직무와 역할의 창출&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;p&gt;이러한 AI 기술 트렌드는 우리 사회를 더욱 스마트하고 효율적으로 변화시킬 것입니다. 하지만 기술의 발전과 함께 윤리적 고려사항과 사회적 영향에 대한 신중한 접근도 필요합니다. 기업과 개인 모두 이러한 변화에 적극적으로 대응하고 준비하는 자세가 필요한 시점입니다.&lt;/p&gt;
&lt;p&gt;[이미지 제안]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;AI 기술 발전을 표현하는 미래지향적 그래픽&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;다양한 AI 응용 분야를 보여주는 인포그래픽&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;인간과 AI의 협업을 상징하는 일러스트레이션&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>IT 이야기</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/231</guid>
      <comments>https://windflex.tistory.com/231#entry231comment</comments>
      <pubDate>Thu, 19 Jun 2025 12:17:28 +0900</pubDate>
    </item>
    <item>
      <title>Agent AI 완벽 가이드: 정의부터 응용까지 상세 분석 리포트</title>
      <link>https://windflex.tistory.com/230</link>
      <description>&lt;h1&gt;Agent AI(에이전트 AI)의 세계로 오신 것을 환영합니다&lt;/h1&gt;
&lt;p&gt;아키텍처별 분류:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;규칙 기반 에이전트&lt;/strong&gt;: 사전 정의된 규칙과 로직을 기반으로 동작&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;학습형 에이전트&lt;/strong&gt;: 머신러닝을 통해 경험으로부터 학습하고 개선&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;계획형 에이전트&lt;/strong&gt;: 목표 달성을 위한 단계별 계획을 수립하고 실행&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;반응형 에이전트&lt;/strong&gt;: 현재 상황에 즉각적으로 반응하여 행동&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. Agent AI의 실제 응용 사례&lt;/h2&gt;
&lt;h3&gt;비즈니스 및 산업 분야:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;자동화된 고객 서비스&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;24/7 고객 응대 챗봇&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;맞춤형 제품 추천 시스템&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;자동 이메일 응답 시스템&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;프로세스 자동화&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;업무 흐름 최적화&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;문서 처리 자동화&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;데이터 분석 및 보고서 생성&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;연구 및 과학 분야:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;과학적 발견&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;신약 개발 보조&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;기후 변화 모델링&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;유전체 분석&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;로보틱스&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;자율 주행 로봇&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;산업용 로봇 제어&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;협업 로봇 시스템&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;4. Agent AI 구현 예제&lt;/h2&gt;
&lt;h3&gt;간단한 규칙 기반 에이전트 예제 코드 (Python):&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;
class SimpleAgent:

    def __init__(self):

        self.knowledge_base = {}

        self.goals = []



    def set_goal(self, goal):

        self.goals.append(goal)



    def sense_environment(self, environment):

        # 환경으로부터 정보 수집

        return environment.get_state()



    def decide_action(self, current_state):

        # 규칙 기반 의사 결정

        if current_state in self.knowledge_base:

            return self.knowledge_base[current_state]

        return &amp;#39;default_action&amp;#39;



    def act(self, action):

        # 선택된 행동 실행

        print(f&amp;#39;Executing action: {action}&amp;#39;)



    def learn(self, state, action, result):

        # 경험으로부터 학습

        self.knowledge_base[state] = action
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;5. Agent AI의 미래와 도전 과제&lt;/h2&gt;
&lt;h3&gt;현재 직면한 과제:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;윤리적 고려사항&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;의사결정의 투명성&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;책임성 문제&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;프라이버시 보호&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;기술적 한계&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;복잡한 상황에서의 의사결정&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;불확실성 처리&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;일반화 능력&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;향후 발전 방향:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;더 강력한 학습 능력&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;적은 데이터로도 효과적인 학습&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;지속적인 학습과 적응&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;향상된 협업 능력&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;인간-AI 협업 개선&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;다중 에이전트 시스템의 발전&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;p&gt;Agent AI는 인공지능 기술의 핵심 분야로서, 자율성과 적응성을 바탕으로 다양한 분야에서 혁신을 이끌고 있습니다. 기술이 발전함에 따라 더욱 지능적이고 효율적인 에이전트가 등장할 것으로 예상되며, 이는 우리의 일상과 산업 전반에 큰 변화를 가져올 것입니다. 다만, 윤리적 고려사항과 기술적 한계를 신중히 다루면서 발전시켜 나가는 것이 중요할 것입니다.&lt;/p&gt;
&lt;h2&gt;1. Agent AI란 무엇인가?&lt;/h2&gt;
&lt;p&gt;Agent AI(에이전트 AI)는 사용자나 다른 시스템을 대신하여 자율적으로 목표를 추구하고 작업을 수행하는 AI 기반 소프트웨어 시스템입니다. 다음과 같은 핵심 특성을 가지고 있습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;자율성(Autonomy)&lt;/strong&gt;: 외부의 직접적인 개입 없이 독립적으로 판단하고 행동&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;목표 지향성(Goal-oriented)&lt;/strong&gt;: 주어진 목표를 달성하기 위해 계획을 수립하고 실행&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;추론 능력(Reasoning)&lt;/strong&gt;: 상황을 분석하고 최적의 행동 방침을 결정&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;학습 능력(Learning)&lt;/strong&gt;: 경험을 통해 성능을 개선하고 지식을 축적&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;환경 인식(Environmental Sensing)&lt;/strong&gt;: 주변 환경을 감지하고 이해&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;적응성(Adaptability)&lt;/strong&gt;: 변화하는 상황에 맞춰 행동을 조정&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. Agent AI의 주요 유형&lt;/h2&gt;
&lt;p&gt;Agent AI는 그 기능과 아키텍처에 따라 다음과 같이 분류됩니다:&lt;/p&gt;
&lt;h3&gt;기능별 분류:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;작업 특화형 에이전트&lt;/strong&gt;: 특정 작업에 최적화된 AI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;범용 에이전트&lt;/strong&gt;: 다양한 작업을 수행할 수 있는 유연한 AI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;다중 에이전트 시스템&lt;/strong&gt;: 여러 에이전트가 협력하는 시스템&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;협업 에이전트&lt;/strong&gt;: 사용자 또는 다른 에이전트와 협력하는 시스템&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/230</guid>
      <comments>https://windflex.tistory.com/230#entry230comment</comments>
      <pubDate>Thu, 19 Jun 2025 12:02:38 +0900</pubDate>
    </item>
    <item>
      <title>[초등학생을 위한 세계명작] 빅토르 위고의 '레 미제라블' - 용서와 사랑의 감동 이야기</title>
      <link>https://windflex.tistory.com/229</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, 친구들! 오늘은 세계적으로 유명한 소설 '레 미제라블'에 대해 함께 알아보려고 해요. 이 이야기는 한 사람이 어떻게 선한 마음과 사랑으로 자신의 인생을 바꾸고, 다른 사람들의 삶도 변화시키는지를 보여주는 감동적인 이야기랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;### 1. 이야기의 배경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프랑스의 1800년대를 배경으로 하는 이 이야기는, 당시 가난하고 힘들었던 사람들의 모습을 보여줍니다. 빅토르 위고라는 유명한 작가가 이 책을 썼는데, 그는 불공평한 세상을 바꾸고 싶었답니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;### 2. 주요 등장인물&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 장발장: 우리 이야기의 주인공이에요. 처음에는 빵을 훔친 죄로 19년 동안 감옥에 있었지만, 나중에는 착한 사람이 되어 다른 사람들을 돕는 영웅이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 미리엘 신부님: 장발장에게 은수저를 주면서 새 삶을 살 수 있게 도와준 착한 신부님이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 코제트: 불쌍한 어린 소녀였지만 장발장이 딸처럼 키워준 아이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 자베르 경감: 법을 중요하게 생각하는 경찰관으로, 계속 장발장을 쫓아다녀요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;### 3. 이야기 줄거리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가난한 장발장은 굶주린 조카를 위해 빵을 훔쳤다가 감옥에 가게 됩니다. 출소 후에는 미리엘 신부님의 은혜로 새 삶을 살기로 결심하죠. 그는 공장 사장이 되어 많은 사람들을 도와주고, 불쌍한 코제트를 입양해서 사랑으로 키웁니다. 하지만 자베르 경감이 계속 그를 쫓아다니면서 과거의 죄를 들추려고 해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;### 4. 우리가 배울 수 있는 점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 용서의 힘: 미리엘 신부님처럼 다른 사람을 용서하고 기회를 주는 것이 얼마나 큰 변화를 만들 수 있는지 배워요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 선한 마음의 중요성: 장발장이 어떻게 나쁜 사람에서 착한 사람으로 변했는지를 보며, 우리도 항상 선한 일을 하려고 노력해야 해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 사랑의 가치: 장발장이 코제트를 돌보면서 보여준 것처럼, 다른 사람을 사랑하고 도와주는 것이 얼마나 소중한지 알 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;### 5. 마무리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'레 미제라블'은 비록 오래전 이야기지만, 지금 우리에게도 매우 중요한 교훈을 주는 책이에요. 용서하는 마음, 다른 사람을 돕고자 하는 마음, 그리고 사랑의 힘이 얼마나 큰지 보여주죠. 여러분도 장발장처럼 어려운 사람들을 도와주는 착한 마음을 가진 사람이 되면 좋겠어요!&lt;/p&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/229</guid>
      <comments>https://windflex.tistory.com/229#entry229comment</comments>
      <pubDate>Thu, 19 Jun 2025 11:42:05 +0900</pubDate>
    </item>
    <item>
      <title>통풍의 효과적인 관리와 예방 가이드</title>
      <link>https://windflex.tistory.com/228</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, 오늘은 통풍의 효과적인 관리와 예방법에 대해 자세히 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 통풍이란 무엇인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통풍은 체내 요산 수치가 비정상적으로 높아져 발생하는 관절염의 한 종류입니다. 주로 발가락 관절에서 시작되며, 극심한 통증과 붓기를 동반하는 것이 특징입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 통풍의 원인과 증상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 주요 원인:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 과다한 퓨린 섭취&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 신장 기능 저하&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 유전적 요인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 비만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 과도한 음주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 대표적 증상:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 갑작스러운 극심한 관절 통증&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 발적과 부종&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 관절 부위 열감&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 활동 제한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 통풍 예방을 위한 생활수칙&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 규칙적인 운동:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 적절한 유산소 운동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 체중 관리를 위한 운동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 관절에 무리가 가지 않는 저강도 운동 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 수분 섭취:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 하루 2L 이상의 물 섭취&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 요산 배출 촉진&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 통풍 관리를 위한 식단 조절&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 피해야 할 음식:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 동물성 내장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 해산물 (정어리, 고등어 등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 알코올 (특히 맥주)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 붉은 고기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 권장되는 음식:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 저지방 유제품&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 통곡물&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 채소류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 저지방 단백질 (닭가슴살, 두부)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 통풍 치료법과 약물 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 급성기 치료:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 비스테로이드성 소염제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 콜히친&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 코르티코스테로이드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 장기 관리:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 요산 저하제 복용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 정기적인 혈중 요산 수치 검사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 의사와의 지속적인 상담&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 결론 및 요약&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통풍은 적절한 생활습관 개선과 식이요법, 그리고 꾸준한 의학적 관리를 통해 충분히 예방하고 관리할 수 있는 질환입니다. 규칙적인 운동, 균형 잡힌 식단, 충분한 수분 섭취를 통해 건강한 생활을 유지하시기 바랍니다.&lt;/p&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/228</guid>
      <comments>https://windflex.tistory.com/228#entry228comment</comments>
      <pubDate>Thu, 19 Jun 2025 11:35:54 +0900</pubDate>
    </item>
    <item>
      <title>Python uv 패키지 관리자 사용 방법 - pip의 강력한 대안</title>
      <link>https://windflex.tistory.com/227</link>
      <description>&lt;h1&gt;Python uv 소개&lt;/h1&gt;
&lt;p&gt;Python 패키지 관리자인 uv는 pip의 강력한 대안으로 등장한 새로운 도구입니다. Rust로 작성되어 뛰어난 성능을 자랑하며, pip보다 최대 10-100배 빠른 속도로 패키지를 설치할 수 있습니다.&lt;/p&gt;
&lt;h2&gt;왜 uv를 사용해야 할까요?&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;속도&lt;/strong&gt;: pip보다 훨씬 빠른 패키지 설치 속도&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;의존성 해결&lt;/strong&gt;: 더 똑똑한 의존성 관리 시스템&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;호환성&lt;/strong&gt;: 기존 pip 명령어와 유사한 사용법&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;안정성&lt;/strong&gt;: Rust로 작성되어 안정적인 성능&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;설치 및 설정&lt;/h1&gt;
&lt;h2&gt;설치 방법&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;
pip install uv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;또는 curl을 이용한 설치:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;
curl -LsSf https://astral.sh/uv/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;주요 사용법&lt;/h1&gt;
&lt;h2&gt;1. 패키지 설치&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;
# 단일 패키지 설치

uv pip install requests



# 여러 패키지 동시 설치

uv pip install numpy pandas matplotlib
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2. 가상환경 생성 및 관리&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;
# 가상환경 생성

uv venv .venv



# 가상환경 활성화

source .venv/bin/activate  # Linux/Mac

.venv\Scripts\activate    # Windows
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3. requirements.txt 사용&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;
# requirements.txt로부터 설치

uv pip install -r requirements.txt



# 현재 환경의 패키지 목록 저장

uv pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;성능 비교 및 장점&lt;/h1&gt;
&lt;h2&gt;pip vs uv 성능 비교&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;대규모 프로젝트에서 패키지 설치 시 최대 100배 빠름&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;메모리 사용량 최적화&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;병렬 다운로드 지원&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;실무 활용 팁&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;기존 프로젝트 마이그레이션&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;pip에서 uv로 쉽게 전환 가능&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;기존 requirements.txt 파일 그대로 사용&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CI/CD 파이프라인 최적화&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;빌드 시간 단축&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;자동화 스크립트 통합 용이&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;결론&lt;/h1&gt;
&lt;p&gt;uv는 Python 패키지 관리의 새로운 표준이 될 잠재력을 가지고 있습니다. 특히 대규모 프로젝트나 CI/CD 환경에서 그 진가를 발휘하며, pip의 한계를 뛰어넘는 훌륭한 대안입니다. 지금 바로 uv를 시작해보세요!&lt;/p&gt;
&lt;p&gt;#python #패키지관리 #uv #개발도구&lt;/p&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/227</guid>
      <comments>https://windflex.tistory.com/227#entry227comment</comments>
      <pubDate>Thu, 19 Jun 2025 11:31:54 +0900</pubDate>
    </item>
    <item>
      <title>외장하드가 MacBook에서 마운트되지 않을 때 해결하는 꿀팁!</title>
      <link>https://windflex.tistory.com/225</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 많은 분들이 겪는 문제 중 하나인 &lt;b&gt;외장하드가 MacBook에서 인식되지만 마운트되지 않는 문제&lt;/b&gt;를 해결하는 방법을 공유하려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어제까지 잘 되던 나의 외장 SSD&lt;br /&gt;갑자기 인식을 못합니다. ㅜ_ㅠ&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;상황 설명&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;**1TB SSD 외장하드 (SanDisk Extreme Pro)**를 MacBook에 연결했지만, Disk Utility에서도 마운트되지 않고, 하드웨어 정보에서만 &quot;ExFAT&quot; 파일 시스템으로 표시되었다는 문제를 겪었습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;첨부 이미지를 보면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;System Information&lt;/b&gt;에서 하드웨어 정보는 제대로 표시되고 있었습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;장치 이름&lt;/b&gt;: Extreme Pro 55AF&lt;/li&gt;
&lt;li&gt;&lt;b&gt;용량&lt;/b&gt;: 1TB&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파일 시스템&lt;/b&gt;: ExFAT&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Partition Map Type&lt;/b&gt;: GPT (GUID Partition Table)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러나, 외장하드는 마운트되지 않았고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Disk Utility&lt;/b&gt;에서의 &quot;검사&quot; 및 &quot;복구&quot; 시도 역시 실패했습니다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;문제의 원인&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이와 같은 문제는 외장하드의 파일 시스템이 손상되었거나, 특정 섹터에 에러가 발생했을 가능성이 큽니다. 특히,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;ExFAT&lt;/b&gt;는 Mac과 Windows 모두에서 호환되지만, 파일 시스템 오류가 생기면 Mac에서 읽기/쓰기 또는 마운트가 불가능한 경우가 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;사전 확인 사항&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째로 해야할 일은, mac &amp;gt; Finder &amp;gt; Application &amp;gt; Utility &amp;gt; System Information 을 열어서 USB자체를 인식하는지 여부를 확인해 보아야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/banRem/btsK8Nvvgzg/USOlV761wK2LgRqqiiQDxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/banRem/btsK8Nvvgzg/USOlV761wK2LgRqqiiQDxK/img.png&quot; data-alt=&quot;mac &amp;amp;gt; Finder &amp;amp;gt; Application &amp;amp;gt; Utility &amp;amp;gt; System Information&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/banRem/btsK8Nvvgzg/USOlV761wK2LgRqqiiQDxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbanRem%2FbtsK8Nvvgzg%2FUSOlV761wK2LgRqqiiQDxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;503&quot; height=&quot;300&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mac &amp;gt; Finder &amp;gt; Application &amp;gt; Utility &amp;gt; System Information&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히, USB 3.1 Bus 아래 SSD를 인식하기는 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eJCS7y/btsK9QSlGa2/cwp93BQDo8CXaFJZQJj5v0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eJCS7y/btsK9QSlGa2/cwp93BQDo8CXaFJZQJj5v0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eJCS7y/btsK9QSlGa2/cwp93BQDo8CXaFJZQJj5v0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeJCS7y%2FbtsK9QSlGa2%2Fcwp93BQDo8CXaFJZQJj5v0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;905&quot; height=&quot;600&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Disk Utility에서 검사/복구/마운트 등을 수행하면 해결된다는 이야기도 있습니다. &lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;다만, 제 경우에는 해당 사항이 없었습니다. 근본적으로 Mac에서 exFat을 인식하지 못하는 상황입니다.&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;해결 방법&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위해 &lt;b&gt;Windows PC&lt;/b&gt;에서 다음 과정을 진행하였습니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Windows PC에 외장하드 연결&lt;/b&gt;&lt;br /&gt;Mac에서는 복구되지 않던 외장하드를 Windows로 연결했더니 정상적으로 인식되었습니다. 그러나 파일에 접근하려고 하면 여전히 오류 메시지가 표시되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;명령 프롬프트 실행&lt;/b&gt; Windows의 검색창에서 &quot;cmd&quot;를 입력하여 &lt;b&gt;명령 프롬프트&lt;/b&gt;를 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;디스크 복구 명령어 실행&lt;/b&gt; 명령 프롬프트에 다음 명령어를 입력했습니다:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 d:는 외장하드가 Windows에서 할당받은 드라이브 레터입니다. 환경에 따라 다를 수 있으니, **내 PC(파일 탐색기)**에서 확인하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;nbsp;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;코드 복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;chkdsk /F d:&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;cmd&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오류 복구 진행&lt;/b&gt; chkdsk는 파일 시스템의 오류를 검색하고, 가능한 경우 자동으로 복구합니다. 몇 분의 시간이 소요되며, 아래와 같은 메시지가 표시될 수 있습니다:이 메시지가 보이면, 복구가 성공적으로 완료된 것입니다.&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;css&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;코드 복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;Windows has made corrections &lt;span&gt;to&lt;/span&gt; the file system.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MacBook에서 재연결&lt;/b&gt; 복구된 외장하드를 다시 MacBook에 연결하면, 이제 정상적으로 마운트되고 모든 데이터에 접근할 수 있었습니다!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XtJiv/btsLak6H07d/zc68tl7QkEQSRkkKSTU2z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XtJiv/btsLak6H07d/zc68tl7QkEQSRkkKSTU2z1/img.png&quot; data-alt=&quot;이제 Macbook 에서도 ExFAT SSD가 정상적으로 동작합니다. ^^&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XtJiv/btsLak6H07d/zc68tl7QkEQSRkkKSTU2z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXtJiv%2FbtsLak6H07d%2Fzc68tl7QkEQSRkkKSTU2z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;479&quot; height=&quot;373&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;373&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이제 Macbook 에서도 ExFAT SSD가 정상적으로 동작합니다. ^^&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Mac에서 해결되지 않을 때 Windows를 활용하라!&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경험을 통해, &lt;b&gt;MacBook에서 외장하드 문제를 해결하지 못할 경우, Windows를 활용하여 chkdsk를 실행&lt;/b&gt;하는 것이 유용한 해결책임을 알게 되었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분의 외장하드가 갑작스럽게 Mac에서 마운트되지 않는다면, 당황하지 말고 위 방법을 시도해 보세요. 추가로, 외장하드를 &lt;b&gt;정기적으로 백업&lt;/b&gt;하고, 중요한 데이터는 한 곳에만 저장하지 않는 습관을 들이는 것도 중요합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분의 Mac과 Windows 사용 경험이 있다면 댓글로 공유해 주세요. 다음에도 유용한 IT 팁으로 찾아뵙겠습니다.  &lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>CHKDSK</category>
      <category>Disk Utility</category>
      <category>exfat</category>
      <category>exfat 불안정</category>
      <category>macbook ssd 인식 오류</category>
      <category>ssd인식오류</category>
      <category>USB 3.0</category>
      <category>외장 ssd</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/225</guid>
      <comments>https://windflex.tistory.com/225#entry225comment</comments>
      <pubDate>Fri, 6 Dec 2024 16:16:38 +0900</pubDate>
    </item>
    <item>
      <title>맥북 M1 Chip GPU에서 pytorch 실행</title>
      <link>https://windflex.tistory.com/224</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맥북 M1 Chip는 Nvidia 그래픽카드를 사용하지 않는다. Apple 자체 개발한 M1 Chip을 사용하며, 이 아키텍처는 CPU와 GPU가 메모리를 공유하는 구조로 되어 있다. 따라서, NVIDA 그래픽카드 메모리에서 구동하도록 만들어진 CUDA 를 사용하지 못한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pytorch + GPU를 사용하는 대부분 실험과 Application이 CUDA를 사용하는 것을 고려할 때, 이것은 매우 심각한 문제라고 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나,&amp;nbsp;애플에서 이부분을 고려하지 않을리 없다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플 또한 CUDA에 해당하는, M1 Chip의 GPU가속을 사용하도록 지원하는 프레임워크 &quot;MPS&quot;를 지원하고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pytorch 또한 이 MPS를 지원한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MPS가 세팅되었는지 확인하기 위해서 다음과 `torch.backends.mps.is_build()` 와 `torch.backend.mps.is_available()`을 사용함으로써 확인할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699848775510&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import torch
print(f&quot;MPS 장치를 지원하도록 build가 되었는가? {torch.backends.mps.is_built()}&quot;)
print(f&quot;MPS 장치가 사용 가능한가? {torch.backends.mps.is_available()}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로&amp;nbsp; Cuda를 사용하는 실험에서 다음과 같은 device를 변수로 사용하도록 많이들 작성한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플 M1 Chip에서는 device를 `mps` 센팅함으로써 기존과 동일한 함수를 m1 chip의 GPU에서 구동 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699848808389&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;device = torch.device(&quot;cuda&quot;) if torch.cuda.is_available() else torch.device(&quot;cpu&quot;)
device = torch.device(&quot;mps&quot;) if torch.backends.mps.is_available() else torch.device(&quot;cpu&quot;)
print(device)
model.to(device)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 이야기/Python</category>
      <category>apple</category>
      <category>CUDA</category>
      <category>GPU</category>
      <category>Macbook</category>
      <category>macbook gpu</category>
      <category>MacBook M1</category>
      <category>mps</category>
      <category>nvidia</category>
      <category>pytorch</category>
      <category>pytorch mac</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/224</guid>
      <comments>https://windflex.tistory.com/224#entry224comment</comments>
      <pubDate>Mon, 13 Nov 2023 17:33:49 +0900</pubDate>
    </item>
    <item>
      <title>hugging face fine tuning with LoRa</title>
      <link>https://windflex.tistory.com/223</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699851620902&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;!pip install transformers datasets evaluate accelerate -q&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; accelerate 는 병렬처리 등을 위한&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699849190336&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;train_dataloader = DataLoader(train_tensor, shuffle=True, batch_size=8)
eval_dataloader = DataLoader(eval_tensor, batch_size=8)
model = AutoModelForSequenceClassification.from_pretrained(&quot;bert-base-cased&quot;, num_labels=5)
optimizer = AdamW(model.parameters(), lr=5e-5)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 HuggingFace에서 Tokenizer와 Classifier를 각각 따로 불러왔어야만 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나, 최근에는 AutoOOOO 등의 Warpper Class가 등장했는데, 이는 hugging Face의 모델명만 입력하면 자동으로 HuggingFace에 등록된 모델을 로딩하는 클래스들이다.&amp;nbsp; 대표적으로, `AutoTokenizer` , `AutoModelForSequenceClassification` 등이 있다. 각각 Tokenizer와 Model에 대한 Auto Class이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1670&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RmAjo/btsAbagp52S/HzNI6GIZlJJbal0uTywjB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RmAjo/btsAbagp52S/HzNI6GIZlJJbal0uTywjB1/img.png&quot; data-alt=&quot;참조 : huggingface&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RmAjo/btsAbagp52S/HzNI6GIZlJJbal0uTywjB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRmAjo%2FbtsAbagp52S%2FHzNI6GIZlJJbal0uTywjB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1670&quot; height=&quot;696&quot; data-origin-width=&quot;1670&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;참조 : huggingface&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NzGHf/btsAalwewSP/z46erEFjSA9PakAVepoC60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NzGHf/btsAalwewSP/z46erEFjSA9PakAVepoC60/img.png&quot; data-alt=&quot;기존에 pretraining matrix W는 고정하고, 여기에 새로운 변화하는 dW만 (Rank가 현저히 작은) 를 더해서.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NzGHf/btsAalwewSP/z46erEFjSA9PakAVepoC60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNzGHf%2FbtsAalwewSP%2Fz46erEFjSA9PakAVepoC60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;408&quot; height=&quot;130&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기존에 pretraining matrix W는 고정하고, 여기에 새로운 변화하는 dW만 (Rank가 현저히 작은) 를 더해서.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPLB9j/btsAhd4GxTH/2VQqk5o6jhaRk8vwYBoCJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPLB9j/btsAhd4GxTH/2VQqk5o6jhaRk8vwYBoCJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPLB9j/btsAhd4GxTH/2VQqk5o6jhaRk8vwYBoCJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPLB9j%2FbtsAhd4GxTH%2F2VQqk5o6jhaRk8vwYBoCJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1380&quot; height=&quot;518&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ef6j0/btsAi56oRXs/3jTP1PKJJDlKuBFyT2jH01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ef6j0/btsAi56oRXs/3jTP1PKJJDlKuBFyT2jH01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ef6j0/btsAi56oRXs/3jTP1PKJJDlKuBFyT2jH01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEf6j0%2FbtsAi56oRXs%2F3jTP1PKJJDlKuBFyT2jH01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1380&quot; height=&quot;518&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lqRq0/btsAjRfuIRq/nDKNcbKDAWrg6GhXyPahUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lqRq0/btsAjRfuIRq/nDKNcbKDAWrg6GhXyPahUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lqRq0/btsAjRfuIRq/nDKNcbKDAWrg6GhXyPahUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlqRq0%2FbtsAjRfuIRq%2FnDKNcbKDAWrg6GhXyPahUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1380&quot; height=&quot;706&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;818&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmrURQ/btsAaYt07oz/llU3HToWhGLiBcVHtFnoS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmrURQ/btsAaYt07oz/llU3HToWhGLiBcVHtFnoS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmrURQ/btsAaYt07oz/llU3HToWhGLiBcVHtFnoS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmrURQ%2FbtsAaYt07oz%2FllU3HToWhGLiBcVHtFnoS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1402&quot; height=&quot;818&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참조] &lt;a href=&quot;https://medium.com/@alexmriggio/lora-low-rank-adaptation-from-scratch-code-and-theory-f31509106650&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://medium.com/@alexmriggio/lora-low-rank-adaptation-from-scratch-code-and-theory-f31509106650&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699863765737&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;LoRA: Low-Rank Adaptation from Scratch &amp;mdash; Code and Theory&quot; data-og-description=&quot;Transformer models can have a lot of parameters which can make fine-tuning them an expensive and time-consuming endeavor that is sometimes&amp;hellip;&quot; data-og-host=&quot;medium.com&quot; data-og-source-url=&quot;https://medium.com/@alexmriggio/lora-low-rank-adaptation-from-scratch-code-and-theory-f31509106650&quot; data-og-url=&quot;https://medium.com/@alexmriggio/lora-low-rank-adaptation-from-scratch-code-and-theory-f31509106650&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fjR5y/hyUu14rS9Q/BctbqCvvnGYbDNK9rUFDo0/img.jpg?width=1200&amp;amp;height=726&amp;amp;face=0_0_1200_726,https://scrap.kakaocdn.net/dn/Y9ERO/hyUuX13b7g/khNWJTRCmBCjVt139dSAM0/img.jpg?width=1358&amp;amp;height=762&amp;amp;face=0_0_1358_762&quot;&gt;&lt;a href=&quot;https://medium.com/@alexmriggio/lora-low-rank-adaptation-from-scratch-code-and-theory-f31509106650&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/@alexmriggio/lora-low-rank-adaptation-from-scratch-code-and-theory-f31509106650&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fjR5y/hyUu14rS9Q/BctbqCvvnGYbDNK9rUFDo0/img.jpg?width=1200&amp;amp;height=726&amp;amp;face=0_0_1200_726,https://scrap.kakaocdn.net/dn/Y9ERO/hyUuX13b7g/khNWJTRCmBCjVt139dSAM0/img.jpg?width=1358&amp;amp;height=762&amp;amp;face=0_0_1358_762');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;LoRA: Low-Rank Adaptation from Scratch &amp;mdash; Code and Theory&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Transformer models can have a lot of parameters which can make fine-tuning them an expensive and time-consuming endeavor that is sometimes&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;medium.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/223</guid>
      <comments>https://windflex.tistory.com/223#entry223comment</comments>
      <pubDate>Mon, 13 Nov 2023 17:28:01 +0900</pubDate>
    </item>
    <item>
      <title>JupyterLab javascript error - Interactive Widget 실행 에러</title>
      <link>https://windflex.tistory.com/222</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;1. JupyterLab Interative Widget 실행 에러 경우&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JupyterLab에서 ML 모듈을 실행 시킬 때, Interactive Widget을 사용하는 경우가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인이 사용하는 경우도 있고, Hugging Face 등에서 제공하는 라이브러리를 사용하면 내부적으로 사용하는 경우도 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google Colab, 혹은 다른 Jupyter Lab 을 SaaS로 제공하는 경우는 버전 매핑을 잘 해두었겠지만, Local에서 설정하는 경우 간혹 버전이 맞지 않는 경우가 존재한다. 다음 사례는 Interactive Widget을 사용하는 경우 javascript가 구동되지 않는 사례이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2172&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNjktD/btsz91DDauM/jMtv2So5XGZKzU67ZyXJJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNjktD/btsz91DDauM/jMtv2So5XGZKzU67ZyXJJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNjktD/btsz91DDauM/jMtv2So5XGZKzU67ZyXJJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNjktD%2Fbtsz91DDauM%2FjMtv2So5XGZKzU67ZyXJJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2172&quot; height=&quot;160&quot; data-origin-width=&quot;2172&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2194&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EzDZ4/btsz9ngjmwI/7fLlFbDomrvGpIakeeZ8sK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EzDZ4/btsz9ngjmwI/7fLlFbDomrvGpIakeeZ8sK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EzDZ4/btsz9ngjmwI/7fLlFbDomrvGpIakeeZ8sK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEzDZ4%2Fbtsz9ngjmwI%2F7fLlFbDomrvGpIakeeZ8sK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2194&quot; height=&quot;196&quot; data-origin-width=&quot;2194&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같인, JupyterLab에서 Web Page 처럼 Interactive한 Component 사용하는 Extention이 실행되지 않는 경우이다. 위에서는 javascript의 Columns, Rows를 구성하는 HBoxModel이 제대로 Display되지 않는 경우 이다. 구글 검색을 통해 찾아 보면,&amp;nbsp; 다음과 같은 해법을 제시하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[ 구글링 결과 제시된 해법]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ipywidgets 다운 그레이드 : ipywidgets==7.5.1&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #3b4045; text-align: left;&quot;&gt;ipympl 다운그레이드 : ipympl==0.9.3&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #3b4045; text-align: left;&quot;&gt;jupyterlab extention enable : `jupyter nbextension enable --py widgetsnbextension`&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 위 설정들을 모두 해 보았는데 해결 되지 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;2. 해결 방법 - JupyterLab 다운그레이드&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 해법은 다음과 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock style1&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v6ClL/btsz92iiG7v/Ef48vKqGPCWSqNVaLt1yL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v6ClL/btsz92iiG7v/Ef48vKqGPCWSqNVaLt1yL1/img.png&quot; data-alt=&quot;JupyterLab에서 js가 실행되지 않는다. (좌), js extention이 실행되는 버전 (우)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v6ClL/btsz92iiG7v/Ef48vKqGPCWSqNVaLt1yL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv6ClL%2Fbtsz92iiG7v%2FEf48vKqGPCWSqNVaLt1yL1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;544&quot; height=&quot;305&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;JupyterLab에서 js가 실행되지 않는다. (좌), js extention이 실행되는 버전 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Macbook의 경우, Jupyter Lab을 Application으로 실행하지 말고, 터미널에서 `python -m jupyterlab`으로 실행해 보자. 이렇게 실행하면 jupyter lab이 Desktop App가 아니라 Browser에서 실행된다. 원칙적으로 이러한 실행은 동일해야 하나, 상기 문제가 발생할 경우, js 실행은 browser 실행이 좀더 직접적인 방법일 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>HBOX</category>
      <category>Interactive Widget</category>
      <category>ipywidget</category>
      <category>javascript extention</category>
      <category>Jupyterlab</category>
      <category>Jupyterlab version</category>
      <category>Python</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/222</guid>
      <comments>https://windflex.tistory.com/222#entry222comment</comments>
      <pubDate>Mon, 13 Nov 2023 11:34:25 +0900</pubDate>
    </item>
    <item>
      <title>2023년 1분기 근로자 산업안전보건교육 TEST</title>
      <link>https://windflex.tistory.com/221</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다시 돌아온 산업안전보건교육&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;법정 의무 교육이라서 정해진 시간만큼 교육이수를 필수로 해야하고요.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;당연히 시험도 있습니다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이게 현장에서 뛰시는 분이 아니라면, 체감도 되지 않고 무의미한 시간으로 여겨지기도 하는데요.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;몇몇 사항은 도움이 되기도 하지만 대다수는 의미 없어 보이는 내용들입니다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;nbsp;Q.01&amp;nbsp;다음&amp;nbsp;중&amp;nbsp;사무실에서&amp;nbsp;근무하는&amp;nbsp;근로자의&amp;nbsp;건강장해를&amp;nbsp;예방하기&amp;nbsp;위한&amp;nbsp;효과적인&amp;nbsp;방법이&amp;nbsp;아닌&amp;nbsp;것은?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;사무실&amp;nbsp;실내오염물질을&amp;nbsp;&amp;nbsp;파악해야&amp;nbsp;한다&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;사무실&amp;nbsp;공기질을&amp;nbsp;적정수준으로&amp;nbsp;관리해야&amp;nbsp;한다&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;실내명암차이가&amp;nbsp;심하고&amp;nbsp;직사광선이&amp;nbsp;잘&amp;nbsp;들어오는&amp;nbsp;구조를&amp;nbsp;유지한다&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;컴퓨터를&amp;nbsp;이용하여&amp;nbsp;장기간&amp;nbsp;앉아서&amp;nbsp;근무하는&amp;nbsp;근로자의&amp;nbsp;건강을&amp;nbsp;관리해야&amp;nbsp;한다&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp; 정답) 3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설명)&amp;nbsp;사무실에서&amp;nbsp;근무하는&amp;nbsp;근로자의&amp;nbsp;건강장해를&amp;nbsp;예방하기&amp;nbsp;위해서는&amp;nbsp;첫째,&amp;nbsp;사무실&amp;nbsp;실내오염&amp;nbsp;물질을&amp;nbsp;파악해야&amp;nbsp;합니다.&amp;nbsp;둘째,&amp;nbsp;사무실&amp;nbsp;공기질을&amp;nbsp;적정&amp;nbsp;수준으로&amp;nbsp;관리하여야&amp;nbsp;합니다.&amp;nbsp;셋째,&amp;nbsp;컴퓨터를&amp;nbsp;이용하여&amp;nbsp;장기간&amp;nbsp;앉아서&amp;nbsp;근무하는&amp;nbsp;근로자의&amp;nbsp;건강을&amp;nbsp;관리해야&amp;nbsp;합니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.02&amp;nbsp;직장&amp;nbsp;내&amp;nbsp;괴롭힘에&amp;nbsp;대한&amp;nbsp;예로써&amp;nbsp;옳지&amp;nbsp;않은&amp;nbsp;것은&amp;nbsp;무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;정당한&amp;nbsp;이유&amp;nbsp;없이&amp;nbsp;휴가나&amp;nbsp;병가,&amp;nbsp;각종&amp;nbsp;복지혜택등을&amp;nbsp;쓰지&amp;nbsp;못하도록&amp;nbsp;압력을&amp;nbsp;행사&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;남성/여성비하&amp;nbsp;행동,&amp;nbsp;성역할의&amp;nbsp;강요&amp;nbsp;또는&amp;nbsp;성&amp;nbsp;정체성&amp;nbsp;등에&amp;nbsp;근거한&amp;nbsp;성적&amp;nbsp;괴롭힘&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;신체적인&amp;nbsp;위협,&amp;nbsp;욕설이나&amp;nbsp;위협적인&amp;nbsp;말을&amp;nbsp;함&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;팀장이&amp;nbsp;팀원에게&amp;nbsp;특정&amp;nbsp;업무에&amp;nbsp;대해&amp;nbsp;계속된&amp;nbsp;보안을&amp;nbsp;요구하는&amp;nbsp;행동&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;4&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;사용자&amp;nbsp;또는&amp;nbsp;근로자가&amp;nbsp;직장에서의&amp;nbsp;지위&amp;nbsp;또는&amp;nbsp;관계&amp;nbsp;등의&amp;nbsp;우위를&amp;nbsp;이용하여&amp;nbsp;업무상&amp;nbsp;적정범위를&amp;nbsp;넘어&amp;nbsp;신체적&amp;middot;정신적&amp;nbsp;고통을&amp;nbsp;주거나&amp;nbsp;근무환경을&amp;nbsp;악화시키는&lt;br /&gt;행위이며,&amp;nbsp;괴롭힘&amp;nbsp;범주에는&amp;nbsp;남성/여성비하&amp;nbsp;행동,&amp;nbsp;성역할의&amp;nbsp;강요,&amp;nbsp;성&amp;nbsp;정체성&amp;nbsp;등에&amp;nbsp;근거한&amp;nbsp;성적&amp;nbsp;괴롭힘도&amp;nbsp;직장내&amp;nbsp;괴롭힘에&amp;nbsp;포함됩니다.&lt;br /&gt;구체적인&amp;nbsp;예로는,&amp;nbsp;①정당한&amp;nbsp;이유&amp;nbsp;없이&amp;nbsp;휴가나&amp;nbsp;병가,&amp;nbsp;각종&amp;nbsp;복지혜택등을&amp;nbsp;쓰지&amp;nbsp;못하도록&amp;nbsp;압력을&amp;nbsp;행사&amp;nbsp;②&amp;nbsp;사적&amp;nbsp;심부름&amp;nbsp;등&amp;nbsp;개인적인&amp;nbsp;일상생활과&amp;nbsp;관련된&amp;nbsp;일을&amp;nbsp;하도록&amp;nbsp;지속,반복적으로&amp;nbsp;지시&amp;nbsp;③&amp;nbsp;신체적인&amp;nbsp;위협이나&amp;nbsp;폭력을&amp;nbsp;가함&amp;nbsp;④&amp;nbsp;욕설이나&amp;nbsp;위협적인&amp;nbsp;말을&amp;nbsp;함&amp;nbsp;⑤&amp;nbsp;집단&amp;nbsp;따돌림&amp;nbsp;등이&amp;nbsp;있습니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;Q.03&amp;nbsp;사업장의&amp;nbsp;안전보건&amp;nbsp;관계자&amp;nbsp;중,&amp;nbsp;해당&amp;nbsp;사업장의&amp;nbsp;안전보건을&amp;nbsp;실질적으로&amp;nbsp;총괄관리하는&amp;nbsp;사람을&amp;nbsp;뜻하는&amp;nbsp;말은?&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;관리감독자&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;안전관리자&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;보건관리자&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;안전보건관리책임자&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;4&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;우리&amp;nbsp;사업장의&amp;nbsp;경우&amp;nbsp;구성원이&amp;nbsp;100인&amp;nbsp;이상&amp;nbsp;근무하는&amp;nbsp;사옥&amp;nbsp;그리고&amp;nbsp;Enterprise&amp;nbsp;수주사업은&amp;nbsp;공사금액&amp;nbsp;20억원&amp;nbsp;이상인&amp;nbsp;사업장에&amp;nbsp;&lt;br /&gt;해당&amp;nbsp;사업장의&amp;nbsp;안전보건을&amp;nbsp;실질적으로&amp;nbsp;총괄관리하는&amp;nbsp;안전보건관리책임자가&amp;nbsp;선임되어&amp;nbsp;있습니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.04&amp;nbsp;산업재해&amp;nbsp;발생&amp;nbsp;후&amp;nbsp;근로자에게&amp;nbsp;신속하고&amp;nbsp;공정하게&amp;nbsp;보상하기&amp;nbsp;위한&amp;nbsp;목적으로&amp;nbsp;제정된&amp;nbsp;법은&amp;nbsp;무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;산업재해보상보험법&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;산업안전보건법&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;재해보상보험법&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;보상재해산업법&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;산업재해보상보험법의&amp;nbsp;목적은&amp;nbsp;근로자의&amp;nbsp;업무상의&amp;nbsp;재해를&amp;nbsp;신속하고&amp;nbsp;공정하게&amp;nbsp;보상하며,&amp;nbsp;재해근로자의&amp;nbsp;재활&amp;nbsp;및&amp;nbsp;사회&amp;nbsp;복귀를&amp;nbsp;촉진하기&amp;nbsp;위하여&amp;nbsp;&lt;br /&gt;이에&amp;nbsp;필요한&amp;nbsp;보험시설을&amp;nbsp;설치ㆍ운영하고,&amp;nbsp;재해&amp;nbsp;예방과&amp;nbsp;그&amp;nbsp;밖에&amp;nbsp;근로자의&amp;nbsp;복지&amp;nbsp;증진을&amp;nbsp;위한&amp;nbsp;사업을&amp;nbsp;시행하여&amp;nbsp;근로자&amp;nbsp;보호에&amp;nbsp;이바지하는&amp;nbsp;것을&amp;nbsp;목적으로&amp;nbsp;한다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.05&amp;nbsp;다음은&amp;nbsp;무엇에&amp;nbsp;대한&amp;nbsp;설명인가?&amp;nbsp;빈&amp;nbsp;칸에&amp;nbsp;알맞은&amp;nbsp;답을&amp;nbsp;쓰시오.&lt;/b&gt;&lt;br /&gt;□□□□□□□□□는&amp;nbsp;공사종류&amp;nbsp;및&amp;nbsp;규모에&amp;nbsp;따라&amp;nbsp;일정금액을&amp;nbsp;도급금액에&amp;nbsp;별도로&amp;nbsp;계상하도록&amp;nbsp;해&amp;nbsp;시공자가&amp;nbsp;건설공사&amp;nbsp;중에&amp;nbsp;안전관리자&amp;nbsp;인건비,&amp;nbsp;안전시설비,&amp;nbsp;기술&amp;nbsp;지도비&amp;nbsp;등에&amp;nbsp;사용함으로써&amp;nbsp;재해예방에&amp;nbsp;기여하는&amp;nbsp;비용을&amp;nbsp;말한다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;산업안전보건관리비&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;사업장에서&amp;nbsp;근무하는&amp;nbsp;근로자의&amp;nbsp;산업재해와&amp;nbsp;건강장해를&amp;nbsp;예방하기&amp;nbsp;위한&amp;nbsp;목적으로&amp;nbsp;건설사업장&amp;nbsp;및&amp;nbsp;본사&amp;nbsp;안전전담부서에서&amp;nbsp;사용하는&amp;nbsp;돈을&amp;nbsp;산업안전보건관리비라고&amp;nbsp;하는데요.&amp;nbsp;산업안전보건관리비는&amp;nbsp;건설공사&amp;nbsp;발주자가&amp;nbsp;건설공사&amp;nbsp;종류&amp;nbsp;및&amp;nbsp;규모에&amp;nbsp;따라&amp;nbsp;일정금액을&amp;nbsp;도급금액에&amp;nbsp;별도로&amp;nbsp;계상,&amp;nbsp;즉&amp;nbsp;예산&amp;nbsp;편성에&amp;nbsp;반영하도록&amp;nbsp;해&amp;nbsp;시공자가&amp;nbsp;건설공사&amp;nbsp;중에&amp;nbsp;안전관리자&amp;nbsp;인건비,&amp;nbsp;안전시설비,&amp;nbsp;기술지도비&amp;nbsp;등에&amp;nbsp;사용함으로써&amp;nbsp;재해예방에&amp;nbsp;기여하는&amp;nbsp;데&amp;nbsp;그&amp;nbsp;목적이&amp;nbsp;있습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;Q.06&amp;nbsp;[O/X&amp;nbsp;문제]&amp;nbsp;재해자의&amp;nbsp;의식이&amp;nbsp;없으면&amp;nbsp;응급처치를&amp;nbsp;바로&amp;nbsp;실시하되,&amp;nbsp;재해자가&amp;nbsp;의식이&amp;nbsp;있는&amp;nbsp;상태라면,&amp;nbsp;실시할&amp;nbsp;응급&amp;nbsp;구조&amp;nbsp;활동에&amp;nbsp;대한&amp;nbsp;내용을&amp;nbsp;설명&amp;nbsp;후&amp;nbsp;동의를&amp;nbsp;구해야&amp;nbsp;한다.&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;O&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;X&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;응급처치를&amp;nbsp;하기&amp;nbsp;전&amp;nbsp;요구조자로부터&amp;nbsp;사전&amp;nbsp;동의를&amp;nbsp;얻어야&amp;nbsp;합니다.&amp;nbsp;만약&amp;nbsp;재해자의&amp;nbsp;의식이&amp;nbsp;없으면&amp;nbsp;응급처치를&amp;nbsp;바로&amp;nbsp;실시하되,&amp;nbsp;재해자가&amp;nbsp;의식이&amp;nbsp;있는&amp;nbsp;상태라면,&amp;nbsp;실시할&amp;nbsp;응급&amp;nbsp;구조&amp;nbsp;활동에&amp;nbsp;대한&amp;nbsp;내용을&amp;nbsp;설명&amp;nbsp;후&amp;nbsp;동의를&amp;nbsp;구하도록&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;Q.07&amp;nbsp;[O/X&amp;nbsp;문제]&amp;nbsp;공사&amp;nbsp;도급&amp;nbsp;내역서에&amp;nbsp;유도자&amp;nbsp;또는&amp;nbsp;신호자의&amp;nbsp;인건비가&amp;nbsp;이미&amp;nbsp;반영되어있거나,&amp;nbsp;타워크레인&amp;nbsp;등&amp;nbsp;양중기를&amp;nbsp;사용하는&amp;nbsp;현장에서&amp;nbsp;유도자&amp;nbsp;또는&amp;nbsp;신호자가&amp;nbsp;유도&amp;nbsp;&amp;middot;&amp;nbsp;신호업무만&amp;nbsp;전담하지&amp;nbsp;않는&amp;nbsp;경우도&amp;nbsp;인건비&amp;nbsp;사용이&amp;nbsp;불가능하다.&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;O&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;X&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;공사&amp;nbsp;도급&amp;nbsp;내역서에서&amp;nbsp;이미&amp;nbsp;계상된&amp;nbsp;금액이고,안전&amp;nbsp;목적의&amp;nbsp;업무만&amp;nbsp;전담하지&amp;nbsp;않는&amp;nbsp;경우&amp;nbsp;사용이&amp;nbsp;불가능합니다.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.08&amp;nbsp;[O/X&amp;nbsp;문제]&amp;nbsp;사업장의&amp;nbsp;안전보건&amp;nbsp;관계자&amp;nbsp;중,&amp;nbsp;해당&amp;nbsp;사업장의&amp;nbsp;생산과&amp;nbsp;관련된&amp;nbsp;업무와&amp;nbsp;그&amp;nbsp;소속&amp;nbsp;직원을&amp;nbsp;직접&amp;nbsp;지휘&amp;nbsp;감독하는&amp;nbsp;사람을&amp;nbsp;뜻하는&amp;nbsp;말은&amp;nbsp;관리감독자이다.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;O&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;X&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;관리감독자는,&amp;nbsp;사업장의&amp;nbsp;생산과&amp;nbsp;관련된&amp;nbsp;업무와&amp;nbsp;그&amp;nbsp;소속&amp;nbsp;직원을&amp;nbsp;직접&amp;nbsp;지휘&amp;middot;감독하는&amp;nbsp;사람을&amp;nbsp;선임하도록&amp;nbsp;법의로&amp;nbsp;규정하고&amp;nbsp;있으며&lt;br /&gt;우리&amp;nbsp;회사는,&amp;nbsp;HR,&amp;nbsp;경영기획,&amp;nbsp;재무회계&amp;nbsp;등&amp;nbsp;순수&amp;nbsp;경영지원직군을&amp;nbsp;제외한&amp;nbsp;전&amp;nbsp;직군을&amp;nbsp;비사무직으로&amp;nbsp;분류하고,&amp;nbsp;비사무직&amp;nbsp;조직의&amp;nbsp;리더를&amp;nbsp;관리감독자로&amp;nbsp;선임하고&amp;nbsp;있습니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.09&amp;nbsp;직무스트레스를&amp;nbsp;관리하는&amp;nbsp;방법&amp;nbsp;중&amp;nbsp;옳은&amp;nbsp;것은&amp;nbsp;무엇인가요?&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;개인&amp;nbsp;스스로&amp;nbsp;받고&amp;nbsp;있는&amp;nbsp;스트레스&amp;nbsp;원인에&amp;nbsp;대한&amp;nbsp;불인지&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;명상,&amp;nbsp;운동,&amp;nbsp;인적교류&amp;nbsp;등&amp;nbsp;자신만의&amp;nbsp;스트레스&amp;nbsp;해소법을&amp;nbsp;찾고&amp;nbsp;실행&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;무분별한&amp;nbsp;약물&amp;nbsp;사용(신경안정제,&amp;nbsp;수면제&amp;nbsp;등)&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;스트레스&amp;nbsp;발생&amp;nbsp;원인을&amp;nbsp;자기&amp;nbsp;자신에게서&amp;nbsp;찾기&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;2&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.10&amp;nbsp;다음&amp;nbsp;중&amp;nbsp;고용노동부&amp;nbsp;고시에&amp;nbsp;따른&amp;nbsp;근골격계&amp;nbsp;질환&amp;nbsp;업무상&amp;nbsp;질병의&amp;nbsp;범위가&amp;nbsp;아닌&amp;nbsp;것은?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;머리&amp;nbsp;부분&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;팔&amp;nbsp;부분&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;허리&amp;nbsp;부분&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;다리&amp;nbsp;부분&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;근골격계&amp;nbsp;질환은&amp;nbsp;반복적인&amp;nbsp;동작,&amp;nbsp;부적절한&amp;nbsp;작업자세,&amp;nbsp;과도한&amp;nbsp;힘의&amp;nbsp;사용,&amp;nbsp;진동&amp;nbsp;및&amp;nbsp;온도로&amp;nbsp;발생하며,&amp;nbsp;팔/다리/허리&amp;nbsp;부분에&amp;nbsp;발생합니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.11&amp;nbsp;다음은&amp;nbsp;안전문화&amp;nbsp;특성&amp;nbsp;중&amp;nbsp;무엇에&amp;nbsp;대한&amp;nbsp;설명인가?&amp;nbsp;&amp;nbsp;&quot;안전하지&amp;nbsp;못한&amp;nbsp;위험을&amp;nbsp;처벌에&amp;nbsp;대한&amp;nbsp;두려움&amp;nbsp;없이&amp;nbsp;자유롭게&amp;nbsp;보고할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;분위기를&amp;nbsp;말합니다.&amp;nbsp;만약&amp;nbsp;망가진&amp;nbsp;설비로&amp;nbsp;인해&amp;nbsp;재해가&amp;nbsp;발생할까&amp;nbsp;걱정되어&amp;nbsp;상급자에게&amp;nbsp;보고하였는데&amp;nbsp;이에&amp;nbsp;대한&amp;nbsp;책임을&amp;nbsp;물거나,&amp;nbsp;처벌한다면&amp;nbsp;누가&amp;nbsp;위험을&amp;nbsp;보고하려&amp;nbsp;할까요?&amp;nbsp;위험&amp;nbsp;요인이&amp;nbsp;보고되어&amp;nbsp;적절한&amp;nbsp;조치가&amp;nbsp;취해지지&amp;nbsp;않으면&amp;nbsp;오히려&amp;nbsp;이로&amp;nbsp;인해&amp;nbsp;재해가&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;보고문화&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;공정문화&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;학습문화&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;유연문화&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;보고문화란&amp;nbsp;안전하지&amp;nbsp;못한&amp;nbsp;위험을&amp;nbsp;처벌에&amp;nbsp;대한&amp;nbsp;두려움&amp;nbsp;없이&amp;nbsp;자유롭게&amp;nbsp;보고할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;분위기를&amp;nbsp;말합니다.&amp;nbsp;만약&amp;nbsp;망가진&amp;nbsp;설비로&amp;nbsp;인해&amp;nbsp;재해가&amp;nbsp;발생할까&amp;nbsp;걱정되어&amp;nbsp;상급자에게&amp;nbsp;보고하였는데&amp;nbsp;이에&amp;nbsp;대한&amp;nbsp;책임을&amp;nbsp;물거나,&amp;nbsp;처벌한다면&amp;nbsp;누가&amp;nbsp;위험을&amp;nbsp;보고하려&amp;nbsp;할까요?&amp;nbsp;위험&amp;nbsp;요인이&amp;nbsp;보고되어&amp;nbsp;적절한&amp;nbsp;조치가&amp;nbsp;취해지지&amp;nbsp;않으면&amp;nbsp;오히려&amp;nbsp;이로&amp;nbsp;인해&amp;nbsp;재해가&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.12&amp;nbsp;직무스트레스의&amp;nbsp;원인으로&amp;nbsp;옳지&amp;nbsp;않은&amp;nbsp;것은&amp;nbsp;무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;업무의&amp;nbsp;균형&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;업무량이&amp;nbsp;높거나&amp;nbsp;노력&amp;nbsp;대비&amp;nbsp;부적절한&amp;nbsp;보상&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;개인생활로&amp;nbsp;인한&amp;nbsp;스트레스&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;직장&amp;nbsp;등&amp;nbsp;사회생활로&amp;nbsp;인한&amp;nbsp;스트레스&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;(주요&amp;nbsp;원인)&amp;nbsp;직무스트레스의&amp;nbsp;가장&amp;nbsp;큰&amp;nbsp;원인은&amp;nbsp;업무의&amp;nbsp;불균형이며,&amp;nbsp;직무와&amp;nbsp;직/간접적으로&amp;nbsp;연관된&amp;nbsp;스트레스&amp;nbsp;원인으로부터&amp;nbsp;야기되는&amp;nbsp;경우가&amp;nbsp;많습니다.&amp;nbsp;직무에&amp;nbsp;따라&amp;nbsp;다르지만,&amp;nbsp;업무량이&amp;nbsp;높거나&amp;nbsp;노력에&amp;nbsp;비해&amp;nbsp;보상이&amp;nbsp;적절하지&amp;nbsp;않은&amp;nbsp;것들도&amp;nbsp;직무스트레스의&amp;nbsp;원인&amp;nbsp;중&amp;nbsp;하나입니다.&lt;br /&gt;(일상&amp;nbsp;환경&amp;nbsp;원인)&amp;nbsp;보통&amp;nbsp;일상생활에서&amp;nbsp;발생하는&amp;nbsp;스트레스가&amp;nbsp;직무스트레스와&amp;nbsp;연결될&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;개인마다&amp;nbsp;요인이&amp;nbsp;모두&amp;nbsp;다르겠지만,&amp;nbsp;체중,&amp;nbsp;가족&amp;nbsp;건강,&amp;nbsp;재산의&amp;nbsp;감소,&amp;nbsp;범죄&amp;nbsp;발생등이&amp;nbsp;있을&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;br /&gt;(근무&amp;nbsp;환경&amp;nbsp;요인)&amp;nbsp;근무&amp;nbsp;환경에서도&amp;nbsp;직무스트레스를&amp;nbsp;발생시킬&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;여러&amp;nbsp;요인들이&amp;nbsp;있습니다.&amp;nbsp;대표적으로&amp;nbsp;사무공간에서&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;소음,&amp;nbsp;진동,&amp;nbsp;조명,&amp;nbsp;환기&amp;nbsp;등&amp;nbsp;이에&amp;nbsp;해당되는데,&amp;nbsp;해당&amp;nbsp;요인들이&amp;nbsp;장기적/지속적으로&amp;nbsp;사무공간에&amp;nbsp;발생하게될&amp;nbsp;경우&amp;nbsp;신체적/정신적으로&amp;nbsp;좋지&amp;nbsp;않은&amp;nbsp;영향을&amp;nbsp;끼치게&amp;nbsp;됩니다.&lt;br /&gt;(사회심리적&amp;nbsp;환경&amp;nbsp;요인)&amp;nbsp;직장&amp;nbsp;등&amp;nbsp;사회활동을&amp;nbsp;하면서도&amp;nbsp;직무스트레스가&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;대표적으로&amp;nbsp;직장&amp;nbsp;내&amp;nbsp;개인의&amp;nbsp;과다한&amp;nbsp;책임이나,&amp;nbsp;직무/직위의&amp;nbsp;불안정,&amp;nbsp;승진기회&amp;nbsp;결여,&amp;nbsp;역할&amp;nbsp;갈등&amp;nbsp;등이&amp;nbsp;있습니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.13&amp;nbsp;[O/X&amp;nbsp;문제]&amp;nbsp;근골격계&amp;nbsp;질환&amp;nbsp;1단계는&amp;nbsp;작업시간&amp;nbsp;동안&amp;nbsp;통증이나&amp;nbsp;피로감을&amp;nbsp;호소하지만&amp;nbsp;하룻밤&amp;nbsp;지나거나&amp;nbsp;휴식을&amp;nbsp;취하게&amp;nbsp;되면&amp;nbsp;증상이&amp;nbsp;없어지는&amp;nbsp;단계이며&amp;nbsp;작업능력의&amp;nbsp;변화도&amp;nbsp;없는&amp;nbsp;단계이다.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;O&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;X&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;근골격계&amp;nbsp;질환은&amp;nbsp;증상과&amp;nbsp;징후의&amp;nbsp;정도에&amp;nbsp;따라&amp;nbsp;발생단계를&amp;nbsp;3단계로&amp;nbsp;나누어&amp;nbsp;정의하고&amp;nbsp;있습니다.&amp;nbsp;1단계는&amp;nbsp;작업시간&amp;nbsp;동안&amp;nbsp;통증이나&amp;nbsp;피로감을&amp;nbsp;호소하지만&amp;nbsp;하룻밤&amp;nbsp;지나거나&amp;nbsp;휴식을&amp;nbsp;취하게&amp;nbsp;되면&amp;nbsp;증상이&amp;nbsp;없어지는&amp;nbsp;단계이며&amp;nbsp;작업능력의&amp;nbsp;변화도&amp;nbsp;없습니다.&amp;nbsp;즉&amp;nbsp;이때는&amp;nbsp;적절한&amp;nbsp;휴식을&amp;nbsp;취하면&amp;nbsp;이전&amp;nbsp;상태로&amp;nbsp;돌아오는&amp;nbsp;것이&amp;nbsp;가능한&amp;nbsp;상태입니다.&amp;nbsp;2단계는&amp;nbsp;작업시작&amp;nbsp;초기부터&amp;nbsp;통증이&amp;nbsp;발생되어&amp;nbsp;증상으로&amp;nbsp;인해&amp;nbsp;밤에&amp;nbsp;잠을&amp;nbsp;못자기도&amp;nbsp;하고,&amp;nbsp;하룻밤이&amp;nbsp;지나도&amp;nbsp;통증이&amp;nbsp;없어지지&amp;nbsp;않습니다.&amp;nbsp;작업능력의&amp;nbsp;감소가&amp;nbsp;동반되며&amp;nbsp;이러한&amp;nbsp;상태가&amp;nbsp;몇&amp;nbsp;달&amp;nbsp;동안&amp;nbsp;지속되는&amp;nbsp;단계입니다.&amp;nbsp;3단계는&amp;nbsp;하루&amp;nbsp;종일&amp;nbsp;통증을&amp;nbsp;느끼며&amp;nbsp;이로&amp;nbsp;인해&amp;nbsp;잠을&amp;nbsp;제대로&amp;nbsp;못&amp;nbsp;자고,&amp;nbsp;작업&amp;nbsp;수행을&amp;nbsp;할&amp;nbsp;수&amp;nbsp;없는&amp;nbsp;상태에&amp;nbsp;이르며&amp;nbsp;다른&amp;nbsp;일에도&amp;nbsp;어려움과&amp;nbsp;통증을&amp;nbsp;느끼게&amp;nbsp;됩니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.14&amp;nbsp;다음&amp;nbsp;근골격계&amp;nbsp;대표질환&amp;nbsp;중&amp;nbsp;범위가&amp;nbsp;다른&amp;nbsp;하나는?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;회전근개건염&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;경추염좌&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;수근관증후군&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;슬개대퇴부&amp;nbsp;통증&amp;nbsp;증후군&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;4&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;슬개대퇴부&amp;nbsp;통증&amp;nbsp;증후군은&amp;nbsp;다리&amp;nbsp;부분의&amp;nbsp;대표적&amp;nbsp;질환이며,&amp;nbsp;경추염좌,&amp;nbsp;경추간판탈출증,&amp;nbsp;회전근개건염,&amp;nbsp;팔꿈치의&amp;nbsp;내/외&amp;nbsp;상과염,&amp;nbsp;수부의&amp;nbsp;건염&amp;nbsp;및&amp;nbsp;건초염,&amp;nbsp;수근관증후군&amp;nbsp;등은&amp;nbsp;팔&amp;nbsp;부분의&amp;nbsp;대표적&amp;nbsp;질환입니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.15&amp;nbsp;[O/X&amp;nbsp;문제]&amp;nbsp;부상자는&amp;nbsp;재빨리&amp;nbsp;이동시키는&amp;nbsp;것이&amp;nbsp;바람직하다.&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;O&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;X&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;2&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;사고&amp;nbsp;발생&amp;nbsp;장소가&amp;nbsp;2차&amp;nbsp;사고가&amp;nbsp;발생할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;위험장소인&amp;nbsp;경우를&amp;nbsp;제외하고는&amp;nbsp;가급적이면&amp;nbsp;부상자를&amp;nbsp;무리하게&amp;nbsp;일으키거나&amp;nbsp;옮기는&amp;nbsp;등의&amp;nbsp;행동은&amp;nbsp;하지&amp;nbsp;않는&amp;nbsp;것이&amp;nbsp;좋습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.16&amp;nbsp;우리&amp;nbsp;생활&amp;nbsp;주변에서&amp;nbsp;흔히들&amp;nbsp;사용되고&amp;nbsp;있는&amp;nbsp;낮은&amp;nbsp;농도의&amp;nbsp;화학물질에&amp;nbsp;누출되어&amp;nbsp;불편감이나&amp;nbsp;증상을&amp;nbsp;나타내는&amp;nbsp;증후군은&amp;nbsp;무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;화학물질&amp;nbsp;과민증&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;신경과민증&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;VDT증후군&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;산소&amp;nbsp;과민증&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;특정&amp;nbsp;시간이나&amp;nbsp;특정&amp;nbsp;건물&amp;nbsp;체류&amp;nbsp;후&amp;nbsp;발생하는&amp;nbsp;건물&amp;nbsp;관련&amp;nbsp;질환은&amp;nbsp;화학물질&amp;nbsp;과민증이라고&amp;nbsp;해서&amp;nbsp;우리생활&amp;nbsp;주변에서&amp;nbsp;흔히들&amp;nbsp;사용되고&amp;nbsp;있는&amp;nbsp;낮은&amp;nbsp;농도의&amp;nbsp;화학물질에&amp;nbsp;누출되어&amp;nbsp;불편감이나&amp;nbsp;증상을&amp;nbsp;나타내는&amp;nbsp;증후군이&amp;nbsp;있습니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.17&amp;nbsp;2021년&amp;nbsp;기준&amp;nbsp;우리나라&amp;nbsp;업무상&amp;nbsp;사고&amp;nbsp;사망자는&amp;nbsp;828명,&amp;nbsp;사고사망만인율은&amp;nbsp;0.43‱입니다.&amp;nbsp;여기서&amp;nbsp;말하는&amp;nbsp;사고사망만인율의&amp;nbsp;정의는&amp;nbsp;무엇일까요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;근로자&amp;nbsp;1만명&amp;nbsp;당&amp;nbsp;재래형&amp;nbsp;재해(사고)&amp;nbsp;사망자수&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;1만&amp;nbsp;근로시간&amp;nbsp;당&amp;nbsp;업무상&amp;nbsp;재해(사고)&amp;nbsp;사망자수&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;근로자&amp;nbsp;1만명&amp;nbsp;당&amp;nbsp;업무상&amp;nbsp;재해(사고)&amp;nbsp;사망자수&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;1만&amp;nbsp;근로시간&amp;nbsp;당&amp;nbsp;재래형&amp;nbsp;재해(사고)&amp;nbsp;사망자수&amp;nbsp;&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;3&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;사고사망만인율은,&amp;nbsp;근로자&amp;nbsp;1만명&amp;nbsp;당&amp;nbsp;업무상&amp;nbsp;재해(사고)&amp;nbsp;사망자수를&amp;nbsp;말하며,&amp;nbsp;여기서&amp;nbsp;근로자는&amp;nbsp;산재보험을&amp;nbsp;적용&amp;nbsp;받는&amp;nbsp;근로자수를&amp;nbsp;말합니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.18&amp;nbsp;ㅇㅇㅇ 회사의 위험성의&amp;nbsp;크기를&amp;nbsp;산출하는&amp;nbsp;방법은?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;행렬법&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;곱셈법&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;덧셈법&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;분기법&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;2&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;위험성의&amp;nbsp;크기는&amp;nbsp;가능성과&amp;nbsp;중대성을&amp;nbsp;행렬법,&amp;nbsp;곱셈법,&amp;nbsp;덧셈법,&amp;nbsp;분기법&amp;nbsp;등의&amp;nbsp;가능성과&amp;nbsp;중대성을&amp;nbsp;조합하여&amp;nbsp;산출하며,&lt;br /&gt;우리&amp;nbsp;회사는&amp;nbsp;가능성&amp;nbsp;5,&amp;nbsp;중대성&amp;nbsp;4의&amp;nbsp;곱셈법을&amp;nbsp;사용하고&amp;nbsp;있습니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.19&amp;nbsp;안전한&amp;nbsp;상태라고&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;없는&amp;nbsp;것은?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;위험을&amp;nbsp;지각하고&amp;nbsp;있을&amp;nbsp;때&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;위험이&amp;nbsp;수용가능한&amp;nbsp;수준의&amp;nbsp;낮은&amp;nbsp;것일&amp;nbsp;때&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;유해인자나&amp;nbsp;부상으로&amp;nbsp;부터&amp;nbsp;자유로운&amp;nbsp;상태&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;위험이&amp;nbsp;수용가능한&amp;nbsp;수준인지&amp;nbsp;아닌지&amp;nbsp;인식하지&amp;nbsp;못한&amp;nbsp;상태&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;4&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;&amp;nbsp;우리가&amp;nbsp;일반적으로&amp;nbsp;안전하다고&amp;nbsp;하는것은&amp;nbsp;위험을&amp;nbsp;지각하고&amp;nbsp;있고&amp;nbsp;그&amp;nbsp;위험이&amp;nbsp;수용가능한&amp;nbsp;수준의&amp;nbsp;낮은&amp;nbsp;것일때를&amp;nbsp;말한다고&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Q.20&amp;nbsp;다음&amp;nbsp;중&amp;nbsp;사무실&amp;nbsp;공기&amp;nbsp;오염물질이&amp;nbsp;아닌&amp;nbsp;것은?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;1)&amp;nbsp;가스&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;2)&amp;nbsp;분진&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;3)&amp;nbsp;곰팡이&lt;br /&gt;&amp;nbsp;&amp;nbsp;4)&amp;nbsp;산소&lt;br /&gt;&amp;nbsp;정답)&amp;nbsp;4&lt;br /&gt;&amp;nbsp;&amp;nbsp;설명)&amp;nbsp;.&lt;br /&gt;&amp;nbsp;---------------------&lt;br /&gt;&lt;br /&gt;&lt;/h4&gt;</description>
      <category>나의 이야기/사회 및 생활</category>
      <category>23년 1분기 산업안전보건</category>
      <category>근골격계 질환</category>
      <category>근로자 법정의무 교육</category>
      <category>산업안전보건 관리비</category>
      <category>산업안전보건 교육 시험</category>
      <category>산업안전보건 교육 테스트</category>
      <category>산업안전보건 테스트</category>
      <category>산업재해보상보험법</category>
      <category>안전보건</category>
      <category>직무스트레스</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/221</guid>
      <comments>https://windflex.tistory.com/221#entry221comment</comments>
      <pubDate>Mon, 3 Apr 2023 13:40:01 +0900</pubDate>
    </item>
    <item>
      <title>[Mac OS] zsh 테마 프롬프트 (cmd prompt) 변경</title>
      <link>https://windflex.tistory.com/220</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ag1gR/btrZo8r87zZ/5pc5W6MmkjAdS1bTWemXy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ag1gR/btrZo8r87zZ/5pc5W6MmkjAdS1bTWemXy1/img.png&quot; data-alt=&quot;ZSH 테마 커스터마이징&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ag1gR/btrZo8r87zZ/5pc5W6MmkjAdS1bTWemXy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAg1gR%2FbtrZo8r87zZ%2F5pc5W6MmkjAdS1bTWemXy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;636&quot; height=&quot;368&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;368&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ZSH 테마 커스터마이징&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;필자는 Mac/Linux 환경에서 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;`iTerm2 + ZSH + Oh-my-zsh`&lt;/span&gt; 조합으로 Terminal을 커스터마이징 하여 사용중이다. 이제는 맥북에서 기본 shell을 ZSH을 사용하기 때문에, 아마도 많은 유저가 필자와 유사한 환경으로 사용중일것 으로 추정하고 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일단, 기본 터미널 세팅을 사용하면, 터미널이 너무 밋밋할 뿐만 아니라 이로 인하여 가독성이 떨어진다. 개발 IDE와 터미널 사용 시간이 거의 비슷한 필자 입장에서, 터미널의 가독성은 생산성과도 직결된다 할 수 있다. 따라서, 터미널의 환경 설정 또한 상당히 예민한 편이다.&amp;nbsp; 필자가 사용하는 터미널 (Terminal) 환경과 테마 적용에 대한 내용은 아래 포스팅을 참조하면 된다.&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[관련글]&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/125&quot;&gt;2020.06.01 - [IT 이야기/IT 상식] - [맥북] 맥북 터미널을 이쁘게 - ZSH 초간단 설치와 커스터마이징 (zhs + iTerm2)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/208&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.10.20 - [IT 이야기/IT 상식] - [MacOS - ZSH] 유용한 플러그인 2종 - 자동완성/하이라이트&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;ZSH 테마 (&lt;span&gt;&lt;b&gt;agnoster)&lt;/b&gt;&lt;/span&gt; 적용 결과 불편한 점 - 프롬프트가 너무 길어..&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이번 포스팅의 내용은, &quot;기본 테마 설정의 불편함&quot;을 거론하고자 한다. 개인의 취향을 모두 마쳐줄 수 없기 때문에, 그 중에서 가장 일반화를 한 것일 것이다. 그러나, 그 중에서 계속 방해되는 것이 있는데, 바로 터미널 (Terminal)에서 &quot;프롬프트 (Prompt) &quot; 표기에 관한 부분은 너무 영향이 크다.&amp;nbsp; 테마는 좋은데 프롬프트가 너무 길다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;물론 Minimal 에 충실한 테마들도 많이 존재한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;먼저 ZSH 테마가 적용된 결과를 살펴 보도록 하자.&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kwV9x/btrZqUNk7Lb/vo9vdI3RpW6VWOI0BKdo80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kwV9x/btrZqUNk7Lb/vo9vdI3RpW6VWOI0BKdo80/img.png&quot; data-alt=&quot;Oh-my-zsh의 테마 (agnoster)가 적용된 iTerm2의 터미널 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kwV9x/btrZqUNk7Lb/vo9vdI3RpW6VWOI0BKdo80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkwV9x%2FbtrZqUNk7Lb%2Fvo9vdI3RpW6VWOI0BKdo80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;887&quot; height=&quot;370&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Oh-my-zsh의 테마 (agnoster)가 적용된 iTerm2의 터미널 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어떤 느낌이 드는가?&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;우선 기본 터미널 대비 가독성이 뛰어나다. 필요한 한 정보가 눈에 쏙 들어오고, 명령어/문자열이 속성에 따라 카테고리가 나뉘어서 매우 보기에 편하다.&amp;nbsp; 그 중에서 프롬프트는 다음과 같이 구성되어 있다.&amp;nbsp; (agnoster 테마를 적용했다. 다른 테마도 비슷할 것이다.)&lt;/h4&gt;
&lt;pre id=&quot;code_1676443513683&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(가상환경 이름) 사용자명@사용자PC이름 &amp;gt; 현재 Directory Path &amp;gt; Git Branch&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;명령어 프롬프트 한중에 많은 정보들이 같이 출력 되어 있기 때문에, 현재 상태를 한 눈에 알아보기 좋다. 그러나, 위 이미지에도 표기한 것과 같이 필자에게는 &quot;개.인.적.&quot;으로 불편한 점들이 있다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1) 혼자 사용하는 Mac Book에&amp;nbsp; &quot;사용자@PC이름&quot;이 모든 명령어 줄에 들어가 있을 필요가 있나?&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 환경이라면 이 또한 매우 중요할 것이다. 만약 `su -` 등을 사용하여 현재 root권한 이라면 큰 문제가 발생할 수도 있으니까.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2) 정보를 주는 것은 좋은데, 명령어 줄에 입력할 공간이 이제 너무 부족한거 아닌가?&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;git 까지 사용하면 그 뒤에 공간은 더욱 줄어들게 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;필자는, 명령어 줄이 다음줄로 넘어가는 것을 싫어한다. 다음줄로 넘어가면 혼동될 수도 있고, 스페이스/엔터 등의 차이로 중대한 오류를 발생할 수도 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;directory Path 경로를 모두 표기할 필요가 있을까?하는 생각도 들기도 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이러한 이유로, ZSH 테마의 명령어 프롬프트 변경할 필요가 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;ZSH 테마 프롬프트 커스터마이징 - 프롬프트 표기 정보 변경&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ZSH 프롬프트 표기되는 정보를 커스터마이징 하기 위해서 다음과 같은 순서 진행이 필요하다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 어떤 테마를 사용하고 있는지 확인한다. (.zshrc 파일 확인)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 적용된 테마 파일(*.zsh-theme)에서 프롬프트 출력 포맷 수정&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1) 적용된 테마 확인 (.zshrc)&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈 디렉토리에 위치한 .zshrc 파일을 열어보자. 잘 모른다면, 터미널을 열고 다음 명령어중 하나를 실행 하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;`open ~/.zshrc`&lt;/li&gt;
&lt;li&gt;`nano ~/.zshrc`&lt;/li&gt;
&lt;li&gt;`code ~/.zshrc`&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;가장 윗부분에서 몇라인 안쪽에 테마 설정이 있을 것이다. 나머지 회색은 전부 &quot;주석&quot;이다.&amp;nbsp; 필자의 경우는 agnoster 테마가 적용되어 있는 것을 확인 할 수 있다. (ZSH_THEME=&quot;agnoster&quot;)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vu4gU/btrZredLFUn/frqgHimcZek8KmQcOpDSHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vu4gU/btrZredLFUn/frqgHimcZek8KmQcOpDSHK/img.png&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;522&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;50.74&quot; style=&quot;width: 50.1547%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vu4gU/btrZredLFUn/frqgHimcZek8KmQcOpDSHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvu4gU%2FbtrZredLFUn%2FfrqgHimcZek8KmQcOpDSHK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;850&quot; height=&quot;522&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yoeyB/btrZk9So4lD/Lavb7zhwqMEsOOga7HlPiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yoeyB/btrZk9So4lD/Lavb7zhwqMEsOOga7HlPiK/img.png&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;360&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.6825%;&quot; data-widthpercent=&quot;49.26&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yoeyB/btrZk9So4lD/Lavb7zhwqMEsOOga7HlPiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyoeyB%2FbtrZk9So4lD%2FLavb7zhwqMEsOOga7HlPiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;569&quot; height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;ZSH 설정 (.zshrc) 파일 - agnoster theme가 적용되어 있다. (좌), 다양한 테마 파일중 agnoster.zsh-theme 파일을 수정한다. (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2) 테마별 설정 파일 수정 ( .zsh-theme 파일 )&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;테마를 확인했다면, 테마에 해당하는 설정 파일을 열어서 수정한다. 테마 파일은 `~/.oh-my-zsh/themes` 위치에 테마의 이름과 동일한 파일명과 &quot;.zsh-theme&quot; 확장자를 가진 파일에 저장되어 있다. 예를 들어 필자는 agnoster 테마를 적용하고 있으므로, 파일의 위치는 다음과 같다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;~/.oh-my-zsh/themes/agnoster.zsh-theme&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;본인에 해당하는 &amp;lt;테마명&amp;gt;.zsh-theme 파일을 열어보면 매우 복잡한 구조의 shell script로 정의되어 있는 것을 확인 할 수 있다. 그러나 잘 살펴보면, 프롬프트를 구성하는 각 영역별로 함수를 나누어 두었고, 색상과 내용을 어떻게 설정할지에 대하여 반복적으로 기술된 내용이다. 앞 부분에는 각 영역들에 대하여 정의하고 가장 마지막에 가서, 각 영역을 조리하여 프롬프트를 생성하는 것을 확인 할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G7Q1d/btrZlXc9MYw/JQx9NswWAnVy17IBU2KBj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G7Q1d/btrZlXc9MYw/JQx9NswWAnVy17IBU2KBj0/img.png&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;339&quot; data-is-animation=&quot;false&quot; style=&quot;width: 66.1614%; margin-right: 10px;&quot; data-widthpercent=&quot;66.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G7Q1d/btrZlXc9MYw/JQx9NswWAnVy17IBU2KBj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG7Q1d%2FbtrZlXc9MYw%2FJQx9NswWAnVy17IBU2KBj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;838&quot; height=&quot;339&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLx4uP/btrZo8MaOTz/8F1SDLTLkbitkekG6jDakK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLx4uP/btrZo8MaOTz/8F1SDLTLkbitkekG6jDakK/img.png&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;489&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.6758%;&quot; data-widthpercent=&quot;33.06&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLx4uP/btrZo8MaOTz/8F1SDLTLkbitkekG6jDakK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLx4uP%2FbtrZo8MaOTz%2F8F1SDLTLkbitkekG6jDakK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;597&quot; height=&quot;489&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;agnoster.zsh-theme 파일의 context 수정 (좌), prompt build 라인 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;본 포스팅에서 수정하려는 부분은 명령어 프롬프트에서의 Context이다. 주석에도 표기 되어 있지만, &quot;Context&quot;는 &quot;user@hostname&quot;으로 표기된다.&amp;nbsp; 여기에서 다음 표기에 집중하여 수정하면 된다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;%n : 사용자 이름 (username)&lt;/li&gt;
&lt;li&gt;%m: PC이름 (hostname)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;필자의 경우 3가지를 테스트 해 보고 마음에 드는 것을 선택하여 사용중이다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;%n@%m : 그대로 사용&lt;/li&gt;
&lt;li&gt;%n : 단독사용하는 MacBook에 PC명이 뭐 중요하겠는가? hostname은 제거한다&lt;/li&gt;
&lt;li&gt;  : username, hostname 모두 필요없지. 예쁜 프롬프트 표시 하나면 되지.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위 3가지 경우중에서 실행해 보고 입맛에 맞게 선택하면 되겠다. 추가적으로 프롬프트 표시는 본인 선호에 따라서 아무거나 하면 된다. 필자는 재미삼아 별모양을 넣어 놓긴 했다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;아무것도 넣지 않은 Minmal도 좋을 듯 하다. 이미 알겠지만, 맥북 환경에서 &lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;`Control + Command + Spacebar`&lt;/span&gt;&lt;/b&gt;를 입력하면 다양한 이모티콘을 입력할 수 있는 창이 열린다.   ✌️⭐︎☆⚡︎&lt;span&gt;&amp;nbsp;&lt;/span&gt;〉&amp;nbsp; 아래는 별모양 프롬프트만 남긴 결과이다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;279&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZGhoY/btrZo77C3MO/KaKizv21tb1eKZQyipiwuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZGhoY/btrZo77C3MO/KaKizv21tb1eKZQyipiwuK/img.png&quot; data-alt=&quot;zsh prompt - 별모양 프롬프트 Context남 남긴 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZGhoY/btrZo77C3MO/KaKizv21tb1eKZQyipiwuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZGhoY%2FbtrZo77C3MO%2FKaKizv21tb1eKZQyipiwuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;279&quot; height=&quot;188&quot; data-origin-width=&quot;279&quot; data-origin-height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;zsh prompt - 별모양 프롬프트 Context남 남긴 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;추가적으로, 본인이 사용하지 않는 기능이 있다면, Prompt 구성에서 아예 제외 시켜도 될것 같다. 다음은 앞서 거론한 Prompt 를 조립(build)하는 부분이다. 테마파일을 가장 마지막에 위치해 있다. 이 부분중 본인이 사용하지 않는 기능은 주석 처리하거나, 삭제하면 간편한 커스터마이징이 될것이다. 가령, 가상환경을 사용하지 않는다면, prompt_virtualenv 라인을 주석처리 해도 될것 이다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1676446811642&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;## Main prompt
build_prompt() {
  RETVAL=$?
  prompt_status
  prompt_virtualenv
  prompt_aws
  prompt_context
  prompt_dir
  prompt_git
  prompt_bzr
  prompt_hg
  prompt_end
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;취향에 맞게 테마를 사용하도록 하자.&amp;nbsp;&lt;/h4&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;기타 - ZSH 추천 테마&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;oh-my-zsh의 기본 설정으로는 &quot;robbyrussell&quot; 테마가 설정되어 있다. 필자는 아래와 같은 테마를 추천한다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;(추천)&lt;/b&gt; agnoster : oh-my-zsh 기본 내장&lt;/li&gt;
&lt;li&gt;&lt;b&gt;(추천)&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Powerlevel10k :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/romkatv/powerlevel10k&quot;&gt;https://github.com/romkatv/powerlevel10k&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;spaceship :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://spaceship-prompt.sh/&quot;&gt;https://spaceship-prompt.sh/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;pure :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/sindresorhus/pure&quot;&gt;https://github.com/sindresorhus/pure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본 사용자는 agnoster를 추천한다. 이래저래 가장 기본적으로 사용하기에 좋다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;고급 사용자는 Powerleve10k를 추천한다. 추천 사유는 테마에서 커스터마이징 자체를 지원해 준다. (config wizard) config wizard의 예시 화면은 아래와 같다. 각 모양과 포함되야할 내용 및 포맷을 설정하도록 지원한다.&amp;nbsp; 다양한 정보를 제공하기 때문에 새로운 경험을 할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;필자는 agnoster 도 상당이 괜찮다고 생각한다. 위에서 설명한 프롬프트 길이만 조절하자.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWfhEw/btrZlrr7rtz/wxPUjdWoKk0SMAioFXKQi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWfhEw/btrZlrr7rtz/wxPUjdWoKk0SMAioFXKQi0/img.png&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;572&quot; data-is-animation=&quot;false&quot; style=&quot;width: 36.8361%; margin-right: 10px;&quot; data-widthpercent=&quot;37.27&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWfhEw/btrZlrr7rtz/wxPUjdWoKk0SMAioFXKQi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWfhEw%2FbtrZlrr7rtz%2FwxPUjdWoKk0SMAioFXKQi0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;908&quot; height=&quot;572&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/st23w/btrZrVye1OS/HBkiD2suqKqKHoG93d5UX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/st23w/btrZrVye1OS/HBkiD2suqKqKHoG93d5UX0/img.png&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;320&quot; data-is-animation=&quot;false&quot; style=&quot;width: 62.0011%;&quot; data-widthpercent=&quot;62.73&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/st23w/btrZrVye1OS/HBkiD2suqKqKHoG93d5UX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fst23w%2FbtrZrVye1OS%2FHBkiD2suqKqKHoG93d5UX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;855&quot; height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;ZSH - Powerlevel10k의 config wizard 를 사용한 커스터마이징 (customizing) (좌), 커스터마이징 적용 결과 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDbiW1/btrZsHT5fRD/9uDvpvup8cY01dOVPZEiN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDbiW1/btrZsHT5fRD/9uDvpvup8cY01dOVPZEiN1/img.png&quot; data-alt=&quot;Powerlevel10k 설정 가능한 테마 형식. 다양한 정보를 다양한 형태로 담을 수 있다. 그러나, 본인에게 맞지 않는 기능은 불필요하므로 사용해 보고 적당한 기능만 사용하자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDbiW1/btrZsHT5fRD/9uDvpvup8cY01dOVPZEiN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDbiW1%2FbtrZsHT5fRD%2F9uDvpvup8cY01dOVPZEiN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1372&quot; height=&quot;135&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Powerlevel10k 설정 가능한 테마 형식. 다양한 정보를 다양한 형태로 담을 수 있다. 그러나, 본인에게 맞지 않는 기능은 불필요하므로 사용해 보고 적당한 기능만 사용하자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ 0h-my-zsh 설치&amp;nbsp; / 삭제]&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) git clone으로 테마 프로젝트 다운로드, 2) 다운로드 완료 후 .zshrc 에서 테마 이름 변경&lt;/p&gt;
&lt;pre id=&quot;code_1676449087929&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 삭제 하기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1676449726355&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ rm -rf -- ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;테마 파일 삭제 후, ~/.zshrc 에서 `ZSH_THEME` 변수 변경&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ Homebrew 설치 ]&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;별도 .zshrc를 변경하지 않아도 된다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1676448883035&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ brew install romkatv/powerlevel10k/powerlevel10k
$ echo &quot;source $(brew --prefix)/opt/powerlevel10k/powerlevel10k.zsh-theme&quot; &amp;gt;&amp;gt;~/.zshrc&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;homebrew 설치가 편리하긴 한데, 아래와 같이 ~/.zshrc 파일에 본인이 직접 수정하지 않은 이상한 라인들이 자꾸 늘어나게 된다.&amp;nbsp;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcZNdp/btrZrZtTD2o/MVGXPGyYg4Em1xs7t2DwRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcZNdp/btrZrZtTD2o/MVGXPGyYg4Em1xs7t2DwRK/img.png&quot; data-alt=&quot;설치 후 변경된 .zshrc 파일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcZNdp/btrZrZtTD2o/MVGXPGyYg4Em1xs7t2DwRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcZNdp%2FbtrZrZtTD2o%2FMVGXPGyYg4Em1xs7t2DwRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;668&quot; height=&quot;373&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;설치 후 변경된 .zshrc 파일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[ 삭제하기 ]&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1676449790465&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ brew uninstall powerlevel10k; brew untap romkatv/powerlevel10k&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ Configuration Wizard&amp;nbsp; 설정 / 재설정 ]&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1676450000006&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ p10k configure&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설치 후 ZSH을 다시 시작하면, configuration wizard가 실행된다. 만약 위자드가 실행되지 않으면 위 명령어를 통해서 강제 실행 하면 된다. 마찬가지로, 설정을 다시 초기화 하고 재 설정 하려면, 위 명령어 (&quot;p10k configure&quot;)를 실행해 주자.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설정 위자드가 완료되면, 홈 디렉터리 밑에 아래와 같은 &quot;.p10k.zsh&quot; 폴더가 생성된다. (자꾸 뭐가 추가되네....)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위자드를 통해서 설정된 값은 해당 폴더 내부에 파일로 저장된다. 그리고, 이것은 ~/.zshrc 파일에서 다시 참조하여 shell을 설정한다. 따라서, 해당 폴더를 삭제해 버리면 설정 위자드가 초기화 되고 다시 설정하도록 할 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n11Iu/btrZqzpuRSK/h9AmeOcx3iXYIwmjJnpSu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n11Iu/btrZqzpuRSK/h9AmeOcx3iXYIwmjJnpSu0/img.png&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;92&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;50.23&quot; style=&quot;width: 49.6463%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n11Iu/btrZqzpuRSK/h9AmeOcx3iXYIwmjJnpSu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn11Iu%2FbtrZqzpuRSK%2Fh9AmeOcx3iXYIwmjJnpSu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;345&quot; height=&quot;92&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y2qxH/btrZqzbYBux/pfgJRifki5yCi2IZ4KK39K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y2qxH/btrZqzbYBux/pfgJRifki5yCi2IZ4KK39K/img.png&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;218&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.1909%;&quot; data-widthpercent=&quot;49.77&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y2qxH/btrZqzbYBux/pfgJRifki5yCi2IZ4KK39K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy2qxH%2FbtrZqzbYBux%2FpfgJRifki5yCi2IZ4KK39K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;810&quot; height=&quot;218&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;powerlevel10k의 설정 위자드를 통한 설정값 저장 디렉토리 (좌), ~/.zshrc의 추가된 설정라인 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Happy Dev.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>agnoster</category>
      <category>config wizard</category>
      <category>oh-my-zsh theme</category>
      <category>PowerLevel10k</category>
      <category>zsh prompt 변경</category>
      <category>zsh theme</category>
      <category>zsh 명령어줄 포맷 변경</category>
      <category>zsh 테마 커스터마이징</category>
      <category>zsh-theme</category>
      <category>테마 변경</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/220</guid>
      <comments>https://windflex.tistory.com/220#entry220comment</comments>
      <pubDate>Wed, 15 Feb 2023 17:08:25 +0900</pubDate>
    </item>
    <item>
      <title>[Mac OS] Python GUI 프레임워크/라이브러리 - PyQt5 설치 시 정지 (Hang) 현상 해결</title>
      <link>https://windflex.tistory.com/219</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RynvR/btrZk9dGtVJ/qLnirCVJljB0RjlloaKThK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RynvR/btrZk9dGtVJ/qLnirCVJljB0RjlloaKThK/img.png&quot; data-alt=&quot;Python GUI Framework - TKinter, PyQt, PySide, Kivy&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RynvR/btrZk9dGtVJ/qLnirCVJljB0RjlloaKThK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRynvR%2FbtrZk9dGtVJ%2FqLnirCVJljB0RjlloaKThK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;344&quot; height=&quot;344&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Python GUI Framework - TKinter, PyQt, PySide, Kivy&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Mac OS 환경 Python GUI&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일반적으로 Python 환경에서 Gui 환경을 구축하는 것은 별다른 작업을 요구하지 않는다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;대표적인 Python GUI 라이브러인 TKinter는 Python 내장 라이브러리 이므로, pip install을 통해서 한번에 환경을 구축할 수 있다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;[ Python 주요 GUI 라이브러리 ]&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;TKinter&lt;/b&gt; - 참조 : &lt;a href=&quot;https://076923.github.io/posts/Python-tkinter-1/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://076923.github.io/posts/Python-tkinter-1/&lt;/a&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(장점) 무지 쉽다. 빠르게 UI를 구성할 수 있다. 따로 설치할것이 별로 없다.&lt;/li&gt;
&lt;li&gt;(단점) 단순하다. UI가 복잡해지면 Layout이 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PyQt4,&lt;/b&gt; PyQt5, 최근 PyQt6 - 참조 : &lt;a href=&quot;https://wikidocs.net/35478&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://wikidocs.net/35478&lt;/a&gt;&lt;br /&gt;(TKinter는 복잡한 GUI를 구성하기에는 번거롭다. UI 자체도 예쁘지는 않다. ==&amp;gt; 좀 더 UI 편의성을 개선한 라이브러리 이다)&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(장점) 상대적으로 고급 UI 개발이 가능하다.&lt;/li&gt;
&lt;li&gt;(단점) 추가 설치가 필요하고, 본격적으로 UI 개발이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PySide&lt;/b&gt; - 참조 : &lt;a href=&quot;https://pypi.org/project/PySide/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://pypi.org/project/PySide/&lt;/a&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;(PyQt는 상용 (Commercial) 사용 불가하기 때문에 대안으로 개발)&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(장점) 개인/업무/상용으로 모두 사용할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;(단점) PyQt와 유사하지만, 다르다. PyQt 대비 자료가 부족하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Kivy - 참조 : &lt;a href=&quot;https://kivy.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kivy.org/&lt;/a&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/b&gt;&amp;nbsp;&lt;br /&gt;(파이썬으로 모바일 앱을 만들어보려는 시도에서 GUI 프레임워크로 발전)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(장점) Python으로 모바일 개발할 수 있는 유일한 프레임워크 이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;(단점) 결과물의 품질을 높이기가 어렵다. 굳이 Python으로 해야하는 생각이 든다. 아직 마이너하다.&lt;br /&gt;Flutter/ReactNative가 CrossPlatform을 지원해주는 시기에 굳이 이렇게 해야하나 하는 생각 ^^;;;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본적인 GUI 환경인, TKinter의 부족한 측면에 대응하여 좀 더 다양한 GUI 환경 구축을 원한다면, PyQt5를 고려해 볼 수 있을 것이다. PyQt 또한 대중적으로 많이 사용하는 라이브러리인 만큼 그에 대한 자료는 매우 많으며, 지속적으로 보완 되어 왔다. 이 덕분에 오늘날의 python3 환경에서 PyQt 사용을 위해서는 `pip install PyQt5` 한줄 입력이면 환경이 완료되는 것이 일반적이다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;[설치 에러] Mac OS 환경 PyQt5 설치 - Hang 해결&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그런데, pyqt5의 라이선스는 상용 (commertial) 사용은 유료 이다.&amp;nbsp; 이 때문에, 설치 시점에 license에 대한 서명을 해야하는 것 같다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1676435812585&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip3 install pyqt5 --config-settings --confirm-license= --verbose&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;우선, pip install 중에 무엇을 하고 있는지 상세하게 살펴보자. --&amp;gt; `--verbose`&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;환경 설정 할 수 있도록 해주자 --&amp;gt; `--config-settings`&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;라이선스 서명에 동의 해 주자. --&amp;gt; `confirm-license=`&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>kivy</category>
      <category>pyQT</category>
      <category>PyQt hang</category>
      <category>pyqt install</category>
      <category>PyQt 설치</category>
      <category>pyside</category>
      <category>python gui</category>
      <category>Python GUI 프레임워크</category>
      <category>tkinter</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/219</guid>
      <comments>https://windflex.tistory.com/219#entry219comment</comments>
      <pubDate>Wed, 15 Feb 2023 15:19:03 +0900</pubDate>
    </item>
    <item>
      <title>[SSH] SSH 연결 자동화 설정 개념/config/문제해결</title>
      <link>https://windflex.tistory.com/218</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;매번 SSH 연결.... 귀찮아~&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Linux/Mac 및 Cloud 환경에서 개발을 하게 되면, 필연적으로 SSH 연결을 사용하게끔 된다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Windows 환경에서는 Putty, WinSCP 등을 사용하여 GUI 환경에서 연결하고, 자동화하는 수단이 다수 제공하고 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그러나, Linux or Mac 등에서는 이러한 자동화 혹은 GUI 툴이 부족한 편이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그도 그럴것이, Terminal에서 기본적으로 OpneSSH Remote Login Client를 지원하기 때문에, 굳이 별도의 Application의 사용 필요성을 느끼지 못하는 부분도 있다. 그러나, 개발과 원격접속이 반복됨에 따라서 이러한 부분도 점점 귀찮아지는 상황이 발생하곤 한다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;OpenSSH의 모든 기능을 이야기 하려면 끝도 없기 때문에, 이번 포스팅에서는 연결 자동화 하는 부분으로 한정하여 이야기 해 보려 한다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;463&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cohxj7/btrXlhLV8wr/bhcJjPk4fThz1z8SXr6HEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cohxj7/btrXlhLV8wr/bhcJjPk4fThz1z8SXr6HEk/img.png&quot; data-alt=&quot;SSH (Secured Shell) 및 비대칭키 암호화, 자동화 설정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cohxj7/btrXlhLV8wr/bhcJjPk4fThz1z8SXr6HEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcohxj7%2FbtrXlhLV8wr%2FbhcJjPk4fThz1z8SXr6HEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;801&quot; height=&quot;463&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;463&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SSH (Secured Shell) 및 비대칭키 암호화, 자동화 설정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;I. SSH 기본 연결&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;SSH의 가장 단순한 사용 형식은 다음과 같다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674789224962&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ ssh &amp;lt;remote server address&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이후 프롬프트에서 Username / Password를 입력하고 로그인 할 수 있다. 그러나, 이러한 user/password 방식은 무작위대입공격(Brute-force Attack)등에 매우 취약하기 때문에 보안 강화 차원에서 Password 문구 대신에 Hash (RSA Private Key)로 이루어진 Key파일로 인증을 진행하는 것이 표준으로 자리 잡고 있다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;SSH는 Secured Shell 의 약자로써, 여기에서 &quot;Secured&quot;는 암화화 연결을 의미한다. 반대로 암호화를 하지 않는 터미널 연결인 Telnet이 있는데, Telnet는 네트워크 상에 평문(텍스트)로 전송이 되기 때문에, Wireshark 등의 Packet Dump를 한다면, 패스워드를 포함한 모든 명령어가 노출될 수 있다. 이러한 단점 때문에, 접속하고자 하는 서버측에서는 암호화 채널을 생성하고, 이를 통하여 통신하도록 한다. 이 때 비대칭키 (Asymetric Key : Public/Private Key 쌍)을 사용하여 암호화 한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이번 포스팅에서는 이러한 연결 Session을 암호화 할 때 사용하는 키를 거론하는 것은 아니다.&amp;nbsp; SSH 접속 시 세션 암호화에 대한 내용은 하단을 참조하도록 하자.&amp;nbsp;이번 포스팅에서 대상으로 하는 것은, 인증 (ex. 로그인)에 대한 키를 대상으로 한다. 간혹, SSH에서 키파일을 거론할 때 이러한 점이 혼동을 유발하기도 하기 때문에 거론한다. 잘 모르겠다면 넘어가도 좋다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;II. SSH 키파일 로그인&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;패스워드 입력 대신 &quot;키파일&quot;을 입력하는 방식으로 SSH를 접속한다면, 수정된 명령어 유형은 다음과 같다.&amp;nbsp; 옵션 -i를 사용하여 키파일을 지정해 주면 된다. 또한, 원격서버를 지정할 때, 키파일을 사용하는 username을 지정해 줄 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674789540193&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ ssh -i keyfilename username@&amp;lt;Remote Server Address&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;옵션 -i : 키파일을 별도 지정한다. 일반적으로, 홈폴더(/Users/username) 하위에 .ssh/에 보관하는 것이 기본설정이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[참조] URI 정의&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷에서 리소스를 지칭하는 URI는 본래적인 의미로, 사용자이름(user)와 패스워드(password)를 포함할 수 있다. 그 예중 하나로, http://user:password@host_address/ 형태가 될 수 있다. 즉, 위 SSH의 예에서 &quot;username@&amp;lt;remote Server Address&amp;gt;&quot; 중 username을 포함하는 것 자체가 URI이다. 이러한 예는, Github를 사용할 때에도 자주 확인할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]&lt;/li&gt;
&lt;li&gt;참조: 위키피디아 ( &lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%86%B5%ED%95%A9_%EC%9E%90%EC%9B%90_%EC%8B%9D%EB%B3%84%EC%9E%90&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ko.wikipedia.org/wiki/%ED%86%B5%ED%95%A9_%EC%9E%90%EC%9B%90_%EC%8B%9D%EB%B3%84%EC%9E%90&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라우드 환경에서 User/Password 로그인 금지&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;최근 클라우드 환경 (AWS, Azure 등)에서는 User/Password 로그인을 금지하도록 SSH 서비스 설정을 하고 있다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설정파일 : /etc/ssh/ssh_config 또는 /etc/ssh/ssh_config.d/*.conf&amp;nbsp;&lt;/li&gt;
&lt;li&gt;설정값 :&lt;br /&gt;&quot;PasswordAuthentication no&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;III. SSH 키파일 로그인 자동화&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;`SSH -i &amp;lt;키파일&amp;gt;`을 통해서 username/password 없이 원격접속이 가능한 것은 알겠다.&amp;nbsp;&lt;br /&gt;몇가지 의문이 생긴다.&lt;br /&gt;키파일은 어떻게 생성하거나 구하는가?&lt;br /&gt;&lt;span&gt;어떤 구조이길래 가능한가? --&amp;gt; 즉, 어떻게 설정해야 하는가?&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그렇다. 키파일을 통한 로그인이 무작정 될리 없다. 해당하는 비대칭키-쌍도 등록을 해 주어야 할것이다. 아무 키파일이나 로그인이 되지는 않을것 아닌가?&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;근본적인 원리는, 구어체로 쓰면 다음과 같다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;비대칭키 (공개키, 개인키 각각 다른 키)를 생성하고,&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;원격서버에 공개키를 주고, 개인키는 내가 보관하고,&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;원격서버에 접속할 때, 로그인으로 인증해 줄 사용자에 키를 할당 해줌&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;좀 더 실제적으로는, 서버에 키-파일을 등록하고 로그인 자동화를 하기 위해서 일반적으로 다음과 같은 단계로 진행한다. (클라우드에 따라서는 key 등록 과정들이 생략될 수 있다.)&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;SSH-Keygen으로 비대칭키쌍 (Public Key, Private Key)를 생성 : ex) ssh-keygen -t rsa&lt;/li&gt;
&lt;li&gt;Server에 인증가능한 대상으로 등록 : authorized_keys에 등록 (public key를 추가함)&lt;/li&gt;
&lt;li&gt;ssh -i 로 접속 --&amp;gt; 로그인 자동화&lt;/li&gt;
&lt;li&gt;추가적인 설정 : ~/.ssh/config 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;1) ssh-keygen으로 비대칭키-쌍 생성&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;키파일의 생성은 여러가지 비대칭키 생성기가 있지만, Linux/Mac 등 환경에 기본 제공하고 있는 `ssh-keygen`명령어를 사용하도록 하자.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674800349059&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ ssh-keygen 
or
$ ssh-keygen -t rsa&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;ssh-keygen 의 옵션 -t 를 통해서 암호화 알고리즘을 설정 할 수 있다. 기본적으로 로그인용 키파일은 RSA알고리즘을 많이 사용한다. SSH Session을 암호화하기 위해서 ecdsa 등을 사용하기도 한다. &lt;br /&gt;옵션 설정은 다음과 같이 설정 할 수 있다.&amp;nbsp; [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;735&quot; data-origin-height=&quot;419&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I49qh/btrXjCvup6L/yK0K0ri2kDHrsH8MRzxyN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I49qh/btrXjCvup6L/yK0K0ri2kDHrsH8MRzxyN0/img.png&quot; data-alt=&quot;ssh-keygen 실행 결과. 옵션 없이 실행하는 경우 기본값으로 RSA알고리즘을 사용한다. passphrase는 키파일에 사용할 패스워드이다. 그냥 엔터를 입력해도 좋고, 키파일에 패스워드를 추가할 때 입력해주면 된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I49qh/btrXjCvup6L/yK0K0ri2kDHrsH8MRzxyN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI49qh%2FbtrXjCvup6L%2FyK0K0ri2kDHrsH8MRzxyN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;735&quot; height=&quot;419&quot; data-origin-width=&quot;735&quot; data-origin-height=&quot;419&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ssh-keygen 실행 결과. 옵션 없이 실행하는 경우 기본값으로 RSA알고리즘을 사용한다. passphrase는 키파일에 사용할 패스워드이다. 그냥 엔터를 입력해도 좋고, 키파일에 패스워드를 추가할 때 입력해주면 된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ssh-keygen 명령어를 실행하면, RSA 공개키/개인키 쌍 (public/private pair)를 생성해 준다. 기본 설정은 각각 다음 파일에 공개키, 개인키를 저장하도록 하고 있다. 별도 파일을 지정하여 저장할 수 있다. 변경없이 진행한다면 그냥 엔터를 눌러주자. (위 실행 결과에서는 &quot;test_key&quot;와 &quot;test_key.pub&quot;에 각각 개인키와 공개키가 저장되었다. )&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개인키 : ~/.ssh/id_rsa&lt;/li&gt;
&lt;li&gt;공개키 : ~/.ssh/id_rsa.pub ==&amp;gt; 이후, 원격 서버 authorized_keys로 복사&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이 때, &lt;b&gt;Fingerprint&lt;/b&gt;가 같이 구해 진다. 출력된다. Fingerprint는 Key File을 검증하기 위해 사용된다. Fingerprint는 공개키의 해쉬값이다. (위 예에서는 SHA256, 알고리즘에 따라서 Salt가 추가 된다.). 이러한 Fingerprint는 ssh 연결에서 &quot;known_hosts&quot;에 사용된다. 또한 github 등의 deploy_key 등의 위변조를 확인 용도로 자주 접할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;`ssh-keygen -l -f &amp;lt;공개키 파일명&amp;gt;` 을 통해서 해당 키의 fingerprint를 다시 확인 할 수 있다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;2) 공개키 원격서버에 등록&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;공개키/개인키를 확보했다면, 서버에 해당 유저가 사용할 키로 등록해 주어야 한다. 이 후 만약 해당 User로 접속할 경우, 패스워드 입력 대신에 Keyfile로 인증을 대체 하게 되는 것이다. 이러한 역할을 하는 파일이 `~/.ssh/authorized_keys`에 등록된다. 이미 등록되어 있는 authorized_keys 파일을 열어서 확인해 보면, 등록한 공개키(public key)와 동일하다. 즉, 인증받고자 하는 공개키를 `~/.ssh/authorized_keys`로 복사해 주면 된다. (기존에 authorized_keys가 존재한다면 다음 행에 공개키를 추가한다.)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1493&quot; data-origin-height=&quot;669&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csn24G/btrXjCI9cYM/orWntMeElSifd5ISADLXW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csn24G/btrXjCI9cYM/orWntMeElSifd5ISADLXW0/img.png&quot; data-alt=&quot;원격 서버의 ~/.ssh/authorized_keys는 클라이언트의 공개키를 복사한 것이다. 이후, 개인키를 사용하여 원격서버에 인증을 요청하면, 권한이 부여된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csn24G/btrXjCI9cYM/orWntMeElSifd5ISADLXW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsn24G%2FbtrXjCI9cYM%2ForWntMeElSifd5ISADLXW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1493&quot; height=&quot;669&quot; data-origin-width=&quot;1493&quot; data-origin-height=&quot;669&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원격 서버의 ~/.ssh/authorized_keys는 클라이언트의 공개키를 복사한 것이다. 이후, 개인키를 사용하여 원격서버에 인증을 요청하면, 권한이 부여된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;즉, 패스워드 입력없이 SSH 접속을 하려면, 다음처럼 진행 하면 된다.&amp;nbsp;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;rsa 공개키/개인키 쌍을 생성한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;rsa 공개키를 원격서버로 복사한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;복사한 공개키를 원격서버의 ~/.ssh/authorized_keys로 변경하거나, 추가 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;2-2) 클라우드 환경 Authorized_keys&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이 과정이 처음에는 어렵고 번거로울 수 있다. 그런데, 요즈음 클라우드 서버들은 이러한 과정은 GUI/Portal로 처리하고 있다. 다음은 Azure Portal에서 VM을 생성할 때, SSH 공개키를 등록하는 과정이다. (VM 생성 이후에더 암호변경 메뉴에서 사후 설정할 수 있다.)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pBUob/btrXm6hBW2U/4keFE0oS86eSJ6Lnfx4KO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pBUob/btrXm6hBW2U/4keFE0oS86eSJ6Lnfx4KO1/img.png&quot; data-alt=&quot;Azure Cloud Portal에서 VM을 생성 시, 관리자 계정에 대한 SSH 공개키 방식으로 설정 ==&amp;amp;gt; 해당 계정에 Authorized_keys에 등록해 준다. 여기에서 사용된 공개키는 새롭게 생성하거나, 기존 키를 사용할 수 있다. 생성된 키는 Key Service에서 별도 관리된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pBUob/btrXm6hBW2U/4keFE0oS86eSJ6Lnfx4KO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpBUob%2FbtrXm6hBW2U%2F4keFE0oS86eSJ6Lnfx4KO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;766&quot; height=&quot;307&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;307&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Azure Cloud Portal에서 VM을 생성 시, 관리자 계정에 대한 SSH 공개키 방식으로 설정 ==&amp;gt; 해당 계정에 Authorized_keys에 등록해 준다. 여기에서 사용된 공개키는 새롭게 생성하거나, 기존 키를 사용할 수 있다. 생성된 키는 Key Service에서 별도 관리된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 설정 완료, Provisioning 이 완료된 후에 해당 서버에 접속하여 확인해 보면 해당 계정의 Authorized_keys에 공개키가 등록되어 있는 것을 확인할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAhzq5/btrXmJmF7Z9/OKe36KkuzNnH3O58Dk9Le0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAhzq5/btrXmJmF7Z9/OKe36KkuzNnH3O58Dk9Le0/img.png&quot; data-alt=&quot;Azure Cloud에서는 Key Service를 VM에 연결할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAhzq5/btrXmJmF7Z9/OKe36KkuzNnH3O58Dk9Le0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAhzq5%2FbtrXmJmF7Z9%2FOKe36KkuzNnH3O58Dk9Le0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;798&quot; height=&quot;118&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;118&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Azure Cloud에서는 Key Service를 VM에 연결할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Azure 및 AWS의 경우, Key Service를 별도록 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;3) SSH 접속 ( ssh -i )&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이제 SSH를 접속하기 위해 shell에서 다음과 같이 입력할 수 있다.&lt;/h4&gt;
&lt;pre id=&quot;code_1674804177091&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ ssh -i ~/.ssh/id_rsa 계정이름@&amp;lt;원격서버&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;ex) ssh -i ~/.ssh/id_rsa user@testcloud.com&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;~/.ssh/id_rsa는 기본값이므로 파일명을 생략이 가능하다. 만약, 다른 파일에 개인키를 저장하고 있다면 이 파일을 명시해 주어야 할것이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;자.! 이제 패스워드 입력 환경 없이, SSH를 접속하는 환경이 세팅 되었다. 해당 명령어가 번거롭다면 스크립트 파일을 만들어서 단순화 할 수 도 있을 것이다. 또한, 다음장에서 소개하는 `.ssh/config`를 통해서 더욱 단순화 할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;4) 발생 가능한 이슈/문제점&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;키파일을 사용하여 SSH를 접속할 때, 빈번하게 발생하는 문제점중 하나는 아래와 같이 &quot;UNPROTECTED PRIVATE KEY FILE!&quot;이라는 경고가 출력되면서 접속이 되지 않는 현상이다.&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVD8rw/btrXm8T5IlA/w84KJiDT11PCFkDCaLJtGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVD8rw/btrXm8T5IlA/w84KJiDT11PCFkDCaLJtGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVD8rw/btrXm8T5IlA/w84KJiDT11PCFkDCaLJtGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVD8rw%2FbtrXm8T5IlA%2Fw84KJiDT11PCFkDCaLJtGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;164&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이것은 최소한의 보안 장치이다.&amp;nbsp; 보안적인 관점에서 다음과 같이 생각해 볼 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;으음.. 이렇게 되면 private key 파일만 있으면 누구든지 서버에 접속할 수 있는거 아냐??&lt;br /&gt;좀...... 위험한데?&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이러한, 이유로 키파일은 좀더 타이트하게 관리되어야 한다. 따라서, 해당 소유자만 읽기(READ)을 가지며, 다른 모든 사용자는 권한을 제거하도록 강제하고 있다. 위 경고는 소유자 외에도 리드권한이 있기 때문에 키파일로써 허가하지 않는다는 의미이다. 만약, 개인PC가 아닌 다중사용자 환경 (서버 등)에서 644 권한을 가진 키파일이 사용된다면, 다른 권한없는 사용자들도 해당 서버에 SSH로 접속할 수 있게 될것이다. 이러한 이유로, 키파일 (개인키)는 600 혹은 400 (소유자만, 읽거나/쓰기 권한)으로 설정되어 있어야만 동작하도록 강제하고 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음과 같이 수정해 주면 해결 할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674805507742&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ chmod 400 ~/.ssh/test_key&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;III. SSH Config&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;우리는 SSH 접속할 때 매번 패스워드 입력을 하는 작업을 단순화 하였다. 그러나, 원격 개발을 하는 과정에서 반복적으로 접속을 하거나 다수개의 터미널을 사용하여 처리하는 일이 빈번하다. 패스워드 입력 없이 SSH를 접속하더라도 매번 키파일을 지정하고, 기억 나지도 않는 IP 혹은 Domain 등을 입력하기도 번거로운 것이 사실이다.&amp;nbsp; Putty 등은 기존 접속이력을 보관하여 버튼 클릭 한번이면 재접속이 가능하기도 하다. (보안에 유의하자...!!!)&lt;/h4&gt;
&lt;pre id=&quot;code_1674805594045&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ touch ~/.ssh/config&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;만약, 이미 config 파일이 존재한다면, 편집으로 추가 하면 된다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;~/.ssh/config 에는 우리가 command line에 Argument로 입력할 사항을 미리 적어두면 된다. 다음은 하나의 예이다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674805765664&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Host remote-server
    HostName mytest-server.example.com
    User testuser
    IdentityFile ~/.ssh/test_key&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째줄에 Host는 나중에 ssh 접속 시 사용할 별칭 (alias)가 된다. 둘째줄 부터 설정 값으로 각각, 접속할 원격서버의 IP/도메인네임, 접속할 사용자 계정, 마지막으로 개인키 파일을 지정한다. 설정이 완료된 경우, 앞으로 다음과 같은 명령만으로 SSH 접속을 단순화 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674805911531&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ ssh remote-server&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;어떠한가? 정말 단순해 지지 않았는가?&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;복잡하게 도메인이름이나, IP를 기억하지 않아도 된다.&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각 서버마다 다른 키파일을 기억하거나 입력하지 않아도 된다.&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;오늘도 삽질을 줄여보자.....&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;IV. 기타&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[ known_hosts ]&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;~/.ssh 디렉토리를 살펴보면, `known_hosts`라는 파일이 있다. 이 파일의 용도는 무엇일까?&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;파일을 열어서 확인해 보면, 다음과 같이 도메인이름과 해시 값들이 열거되어 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674806287675&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ cat ~/.ssh/known_hosts&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zu3sG/btrXmyy74GE/31xgM4OCBjHyy9yd1m7hN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zu3sG/btrXmyy74GE/31xgM4OCBjHyy9yd1m7hN0/img.png&quot; data-alt=&quot;known_hosts 파일 내용. 도메인-해시값이 나열되어 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zu3sG/btrXmyy74GE/31xgM4OCBjHyy9yd1m7hN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZu3sG%2FbtrXmyy74GE%2F31xgM4OCBjHyy9yd1m7hN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1015&quot; height=&quot;119&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;known_hosts 파일 내용. 도메인-해시값이 나열되어 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;결론적으로, `known_hosts`파일은 fingerprint 값을 저장하고 있다. 앞서 잠깐거론 했듯이, fingerprint는 공개키의 해시값에 해당한다. 결국, 이 fingerprint라는 해시값은 해당 Client(접속하는 서버도 Client가 될 수 있다)에서 인지하고 있는 원격서버가 정확한지? 변조는 없었는지를 검증하는 용도이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;원격 서버가 SSH 데몬서비스를 오픈하면 기본적으로 세팅된 공개키가 존재한다. 이것은 SSH에서는 HostKey라고 한다. 또한, 이 HostKey는 SSH 데몬서비스인 sshd의 설정값에 따라서 다른 인코딩 알고리즘을 사용한다. 다음은 서버에 일반적으로 존재하는 지원하는 알고리즘별로 공개키를 fingerprint 해 둔 파일들이다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HKVUk/btrXmylKAUQ/nmIys6igE7iVHcYgjkgK71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HKVUk/btrXmylKAUQ/nmIys6igE7iVHcYgjkgK71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HKVUk/btrXmylKAUQ/nmIys6igE7iVHcYgjkgK71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHKVUk%2FbtrXmylKAUQ%2FnmIys6igE7iVHcYgjkgK71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;802&quot; height=&quot;123&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예를 들면, 위 예제의 서버에서는 ed25519 알고리즘을 HostKey로 사용하고 있다. 따라서, Client (위 예제 서버에 접속하는 Client)의 `known_host`에는 위에 표기된 `ssh_host_ed25519_key.pub`에 기록된 해시값이 입력되게 된다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그런데, 이러한 fingerprint는 왜......? 필요한건데..?&lt;br /&gt;&lt;/span&gt;결론은 보안 때문이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;앞서 거론했듯이, 핑거프린팅(fingerprint)은 공개키를 검증하는데 사용하고 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;우리가, 최초 ssh로 서버에 접속하게 되면, fingerprint를 known_host에 등록하겠냐는 질문을 받는다. (대부분 엔터를 입력하므로 등록된다.) 따라서, 우리는 `www.example.com`이라는 원격서버에 접속해서, 공개키를 기준으로 핑거프린트를 등록해 두었다. 이것은 다음과 같은 작업을 의미한다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; &lt;a href=&quot;http://www.example.com의&quot;&gt;www.example.com의&lt;/a&gt; 공개키는 &quot;xxx&quot;값이다. 이것을 빠르게 검증하기 위해 fingerprint 사용할께~&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 상황에서 만약, 어떠한 이유에서 공개키가 변경될 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동일한 &quot;ww.example.com&quot;에서 hostkey가 변경된 경우 --&amp;gt; 이런 경우는 정상이므로 제외하도록 하자.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&quot;www.example.com&quot;을 위장한 다른서버로의 접속&lt;/li&gt;
&lt;li&gt;/etc/hosts 파일 변경 등으로 인한, 다른 서버 접속&lt;/li&gt;
&lt;li&gt;중간에 proxy 이 중간에 껴서 대상 서버가 달라지는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;특히, 마지막의 경우를 우리는 중간자공격 (MITM : Man In The Middle)이라고 하는데, fingerprint는 이러한 공격을 방지하고자 함이다. 내가 분명히 &quot;www.example.com&quot;으로 접속했을 때, 접속한 대상이 과거에 기록된 &quot;www.example.com&quot;의 HostKey와 동일함을 확인하는 것이다. 그렇지 않고, 위장서버 또는 중간에 가로채기 등이 존재하는 경우, HostKey가 변경될 것이고, 이 변경사항을 Fingerprint로 빠르게 확인 할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;[Visual Studio Code - Extension]&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjexBj/btrXlgTKKiN/THmEMtblHSUHno3tRtn5kK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjexBj/btrXlgTKKiN/THmEMtblHSUHno3tRtn5kK/img.png&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;422&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;29.61&quot; style=&quot;width: 29.2697%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjexBj/btrXlgTKKiN/THmEMtblHSUHno3tRtn5kK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjexBj%2FbtrXlgTKKiN%2FTHmEMtblHSUHno3tRtn5kK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;644&quot; height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btWwec/btrXnIgGBJL/SKmD4DffZpSVPqwkza1450/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btWwec/btrXnIgGBJL/SKmD4DffZpSVPqwkza1450/img.png&quot; data-origin-width=&quot;856&quot; data-origin-height=&quot;236&quot; data-is-animation=&quot;false&quot; style=&quot;width: 69.5675%;&quot; data-widthpercent=&quot;70.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btWwec/btrXnIgGBJL/SKmD4DffZpSVPqwkza1450/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtWwec%2FbtrXnIgGBJL%2FSKmD4DffZpSVPqwkza1450%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;856&quot; height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Visual Studio Code에서는 다양한 확장App을 제공한다. 이중에서 Remote-SSH를 제공하는데, Microsoft가 제공/유지 관리하여 상당히 신뢰성을 가지고 사용해 볼만 하다. &quot;Remote-SSH 호스트에 연결&quot; 명령어를 통하여 쉽게 서버에 접속하고, Visual Stuiod Code 환경으로 편집/개발을 할 수 있으며, Terminal도 오픈하여 사용할 수 있다. 굳이 Code를 작성하는 시점이 아니더라도, Terminal 사용 환경으로도 우수한 환경을 지원한다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그러나, 항상 Visual Studio Code를 사용할 수 있는 환경만 있는 것은 아니므로, 기본기는 갖추어야 할 것이다. 툴을 최대한 이용하되 툴에 종속되지는 말자....!!!&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>.ssh/config</category>
      <category>authorized_keys</category>
      <category>Fingerprint</category>
      <category>known_hosts</category>
      <category>SSH</category>
      <category>ssh -i</category>
      <category>ssh config</category>
      <category>UNPROTECTED PRIVATE KEY FILE</category>
      <category>비대칭키 ssh</category>
      <category>패스워드 없이 SSH 접속</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/218</guid>
      <comments>https://windflex.tistory.com/218#entry218comment</comments>
      <pubDate>Fri, 27 Jan 2023 17:56:31 +0900</pubDate>
    </item>
    <item>
      <title>[MacOS/Linux] 자꾸 패킷을 날리는 것은 누구인가? (ft. netstat, lsof, Streamlit)</title>
      <link>https://windflex.tistory.com/217</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;Python FastAPI로 간단한 RestAPI 서버를 테스트 중입니다. (클라우드 서버에서)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그런데, 해당하는 개발 서버에 지속적으로 패킷을 발송(Send)하는 대상이 있습니다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;지속적으로, &quot;GET /healthz&quot;를 보내고 있습니다. 처음에는 그냥 그런가보다 했는데, 자꾸 발송하니 테스트에 방해가 되었습니다.&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;1) Log를 확인해 봅니다.&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;2) 대상 출발지를 확인해 봅니다.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;3) 대상 IP를 확인하니, 어처구니 없게도 본인의 공인 아이피 입니다.&amp;nbsp; 헐~&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;447&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfGnmr/btrXjD7figa/oXpmbnnGZFagcIWG4fLMCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfGnmr/btrXjD7figa/oXpmbnnGZFagcIWG4fLMCK/img.png&quot; data-alt=&quot;어떤 프로세스가 지속적으로 패킷을 보내는가? 너무 귀찮습니다. 로그도 계속 쌓여서 테스트하고자 하는 로그찾기도 귀찮아 집니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfGnmr/btrXjD7figa/oXpmbnnGZFagcIWG4fLMCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfGnmr%2FbtrXjD7figa%2FoXpmbnnGZFagcIWG4fLMCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;507&quot; height=&quot;447&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;447&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;어떤 프로세스가 지속적으로 패킷을 보내는가? 너무 귀찮습니다. 로그도 계속 쌓여서 테스트하고자 하는 로그찾기도 귀찮아 집니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;테스트중인 POSTMan, Proxy 등은 /healthz 라는 URI를 호출하지 않습니다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그렇다면, 내 개발장비의 어느 프로세스 인가가 계속 루프를 돌면서 호출하고 있는게 분명합니다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;누구냐..? 넌..?&lt;br /&gt;나를 귀찮게 하는 것은 누구인가?&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;4) 로컬PC (mac)에서, 네트워크가 연결되어 있는 정보를 살펴 봅니다.&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1674736723314&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ netstat -ant | grep 8080&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음과 같이 목적지 서버에 8080포트로 연결하여 ESTABLISHED 되어 있는 연결이 있습니다. 신기한것은 TIME_WAIT 되었지만 몇놈 더 있었다는 것입니다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;88&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JdFa2/btrXcpcmkKz/O3kUFgKBCbNaRzgafBZbRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JdFa2/btrXcpcmkKz/O3kUFgKBCbNaRzgafBZbRk/img.png&quot; data-alt=&quot;목적지 서버에 접속하여 커넥션을 유지하고 있는 프로세스가 있다. (netstat -ant)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JdFa2/btrXcpcmkKz/O3kUFgKBCbNaRzgafBZbRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJdFa2%2FbtrXcpcmkKz%2FO3kUFgKBCbNaRzgafBZbRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;635&quot; height=&quot;88&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;88&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;목적지 서버에 접속하여 커넥션을 유지하고 있는 프로세스가 있다. (netstat -ant)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다시 netstat 를 서버 IP로 잡아보고, 어떤 프로토콜을 사용하는지 살펴보았습니다.&amp;nbsp; 연결하여 사용하고 있는 ssh는 문제가 없어 보입니다. &quot;http-al&quot;이 수상해 보입니다. http protocol을 사용하고 있는 녀석입니다. http 프로토콜은 기본적으로 한번 접속하고 connection을 끊어 주는데, 지속 연결하고 있습니다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span class=&quot;imageblock&quot;&gt;&lt;span data-url=&quot;//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png&quot; data-phocus=&quot;//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png&quot;&gt;&lt;img src=&quot;//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png&quot; srcset=&quot;//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png&quot;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;5) lsof 명령으로 정확한 프로세스/파일명을 찾는다.&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;http를 사용하는 어떤 프로세스인지, 정확히 실행파일 단위로 알고 싶습니다. 이럴 때, `lsof` 명령어는 매우 요긴하게 사용할 수 있습니다.&amp;nbsp; `lsof`명령어는 List of File의 약자로 Linux/Unix계열에서 오픈되어 있는 파일을 나열하는 명령어 입니다. 아시다시피, Linux/Unix계열의 모든것은 파일형태로 관리하기 때문에 네트워크 소켓 또한 파일로 관리됩니다. 따라서, lsof를 사용하면 열려있는 소켓과 이를 사용하는 프로세스를 확인 할 수 있습니다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음은 포트 8080을&amp;nbsp; 열고있는 파일을 나열합니다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674737736618&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ lsof -i:8080&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4XHZI/btrXiPfNAH7/Rv7lqdrZQJX1fi6g17RsrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4XHZI/btrXiPfNAH7/Rv7lqdrZQJX1fi6g17RsrK/img.png&quot; data-alt=&quot;lsof 명령어로 8080 포트를 열고 있는 프로세스는 무엇인지 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4XHZI/btrXiPfNAH7/Rv7lqdrZQJX1fi6g17RsrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4XHZI%2FbtrXiPfNAH7%2FRv7lqdrZQJX1fi6g17RsrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1039&quot; height=&quot;67&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;lsof 명령어로 8080 포트를 열고 있는 프로세스는 무엇인지 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;흐음... Google 입니다. Google + HTTP ==&amp;gt; Chrome ?&lt;br /&gt;&lt;/span&gt;PID == 569&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;6) 정확한 Application 확인&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;확인을 위해서 `ps -ef`를 사용하여 정확한 실행 파일명을 찾아 보았습니다.&amp;nbsp; &quot;/Applications/Google Chrome.app&quot;를 확인하였습니다. Chrome 브라우저가 맞습니다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1218&quot; data-origin-height=&quot;141&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bP4aee/btrXe9AfHMM/W87HF1BwaRwFNFGQmBuFU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bP4aee/btrXe9AfHMM/W87HF1BwaRwFNFGQmBuFU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bP4aee/btrXe9AfHMM/W87HF1BwaRwFNFGQmBuFU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbP4aee%2FbtrXe9AfHMM%2FW87HF1BwaRwFNFGQmBuFU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1218&quot; height=&quot;141&quot; data-origin-width=&quot;1218&quot; data-origin-height=&quot;141&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;필자는 Chrome의 탭을 30~40개 띄워놓고 작업을 하는데, 이중에서 무엇인가 있나 봅니다. 탭을 하나 하나 확인 결과, Chrome Browser에 띄워 놓은 Streamlit 이었습니다. &lt;a title=&quot;Streamlit&quot; href=&quot;https://streamlit.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Streamlit&lt;/a&gt;은 Frontend/Backend 모두 포함하고 있는데, FrontEnd의 Javascript로 변환된 코드 중에서 지속적으로 Health Check 를 확인하는 코드가 포함되어 있는 것을 확인했습니다.&amp;nbsp; Streamlit을 사용하시는 분은 참조하시기 바랍니다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;에효~~ 결국 브라우저에서 원하지 않는 health Check를 하는 녀석이네요.&lt;br /&gt;&lt;/span&gt;집 앞에 있는 파랑새를 잡은 느낌입니다만, 개발하는 과정은 언제나 이렇습니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>health check</category>
      <category>http Established</category>
      <category>http-alt</category>
      <category>lsof</category>
      <category>netstat</category>
      <category>ps -ef</category>
      <category>streamlit</category>
      <category>이상한 연결 찾기</category>
      <category>지속적 패킷 발송</category>
      <category>패킷 발송 반복</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/217</guid>
      <comments>https://windflex.tistory.com/217#entry217comment</comments>
      <pubDate>Thu, 26 Jan 2023 22:03:44 +0900</pubDate>
    </item>
    <item>
      <title>[Python] 패키지 배포 리스트 관리 (ft. Requirements.txt 포맷팅 오류)</title>
      <link>https://windflex.tistory.com/216</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;이번 포스팅이서 다루고자 하는 내용은 Python 소스를 배포하고 구동하는 발생하는 어려움 중 하나의 대해서 이야기 하고자 한다. 결론부터 이야기하면, Python 소스를 배포할 때 사용하는 패키지 리스트 (requirements.txt)가 간혹 호환성 (Compatible)이 없을 때가 있다. 필자의 경우는, 이런경우를 수정하고 배포하거나 검증/수정을 하는데, 다른 개발자가 개발한 배포 버전에서 이런 부분이 다수 발견되었다.&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RC5wR/btrWzVh1Hhi/Nih6KKccKJDcijIVLdetn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RC5wR/btrWzVh1Hhi/Nih6KKccKJDcijIVLdetn0/img.png&quot; data-alt=&quot;python 패키지 배포 시 requirements.txt의 설치 목록 포맷팅 오류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RC5wR/btrWzVh1Hhi/Nih6KKccKJDcijIVLdetn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRC5wR%2FbtrWzVh1Hhi%2FNih6KKccKJDcijIVLdetn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;391&quot; height=&quot;391&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;python 패키지 배포 시 requirements.txt의 설치 목록 포맷팅 오류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다른 분들도 이런 경우가 발생하지 싶어서 포스팅을 남겨 본다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;[순서]&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) Python 패키지 배포 (기본사항 리마인드)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) Python 패키지 리스트 중 발생 가능한 이슈&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3) 문제 발생 원인&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4) 문제 해결 방안&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;[결론]&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일관된 requirements.txt 포맷을 출력하기 위해서 다음 명령어를 사용하자.&lt;/h4&gt;
&lt;pre id=&quot;code_1674024700551&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip list --format=freeze &amp;gt; requirement_pip_list.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;1. Python 패키지 배포, 가상환경 생성 및 배포 (리마인드)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Python으로 모듈 개발을 완료한 후에는 이제 Staging/Production 환경에 구축하고, 구동을 해야 할것이다. 이미 잘 알고 계시듯, Python에서는 개발환경과 동일한 환경을 구축 할 수 있도록 가상환경 체계와 설치환경을 제공한고 있다. 패치지 관리자가 지원하는 가상환경 (VirtualEnv)과, 설치된 패키지 목록(requirements.txt)을 통해서 수월하게 환경을 재구축 할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;간략히 요약해 보자. (PIP 기준)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;[ 설치 목록 생성 ]&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설치된 패키지 목록은 아래와 같이 상태를 고정 (freeze)하면서 목록을 얻을 수 있다. 다음 명령은 pip를 사용하여 requirements.txt를 생성한다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674016924207&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip freeze &amp;gt; requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;[ 가상환경 생성 및 패키지 설치 ]&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음은 Python 기본 내장 모듈인 `venv`를 사용하여 가상환경을 생성하고, requirements.txt에 표기된 패키지를 설치한다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674018302763&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python -m venv .venv
source .venv/bin/activation
pip install -r requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;가상환경을 생성할 때, venv 외에 virtualenv 또는 conda env를 사용할 수도 있다. virtualenv의 용법은 venv와 거의 유사하면, conda의 경우는 다음과 같이 가상환경을 생성할 수 있다.&amp;nbsp; ex) `conda create -n &amp;lt;가상환경 이름&amp;gt; python=3.9`&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Conda 등 가상환경 생성에 대한 부분은 다음 포스팅을 참조 바란다:&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Conda-Jupyter] Conda 가상환경과 Jupyter Kernel 연동/생성/삭제&lt;/a&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;&lt;b&gt;[ Docker 환경에서 배포/설치하는 경우 ]&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Docker/Container의 경우에는 Container 자체가 가상환경이며, 초기 상태를 가정하고 있으므로 굳이 새로운 가상환경을 만들 필요는 없을 것이다. 이 경우, 아래와 같이 COPY명령어로 requirementx.txt를 복사하고, RUN명령어로 pip install을 실행해 주면 된다. 다음은 Dockerfile의 일부 이다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674018547234&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;COPY ./requirements.txt /path/to/requirements.txt
RUN pip install -r requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;2. Python 패키지 목록 발생 가능 문제점&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위에서 우리는 Python 패키지 설치목록을 배포하고, 이를 통해서 개발환경을 재구축하는 방법에 대하여 상기하여 보았다. 이제 발생가능한 문제점을 살펴보자. 아래는 정상적인 상태에서 패키지 목록 (requirements.txt)의 유형을 표기한 것이다. 아래와 같이 requirements.txt는 설치된 패키지 이름과 버전을 표기하고 있는 텍스트 파일일 뿐이다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674019215712&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;패키지이름1==버전
패키지이름2==버전
패키지이름3==버전&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음은 실제 사례 (requirements.txt) 중 일부이다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674019244597&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
matplotlib==3.6.0
mkl-fft==1.3.1
mkl-service==2.4.0
...&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그런데, 개발을 진행하다가 보면, 다음과 같은 이상한 문자열을 보기도 한다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674019349928&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;numpy @ file:///tmp/abs_653_j00fmm/croots/recipe/numpy_and_numpy_base_1659432701727/work&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;잘 살펴보면, 패키지 이름을 나열하고, 그 패키지 파일이 어디에 있는지를 표기하고 있는것으로 보인다. 기본적인 pip는 PyPy를 기반으로 &amp;lt;패키지명&amp;gt;, &amp;lt;버전&amp;gt;만 표기하면 그때 그때 다운로드 받아서 설치하는 구조인데, 상기의 표기는 무엇인가 기본적인 정책에 부합하지 않는다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;아래는 실제 필자가 사용하는 패키지 중 일부에서 발췌한 실 사례이다.&amp;nbsp; certifi, mkl-random, numpy 등이 비정상적인 포맷으로 표기되어 있는 것을 볼수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674019117953&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;blinker==1.5
cachetools==5.2.0
certifi @ file:///opt/conda/conda-bld/certifi_1663615672595/work/certifi
cffi==1.15.1
charset-normalizer==2.1.1
click==8.1.3
commonmark==0.9.1
contourpy==1.0.5
decorator==5.1.1
entrypoints==0.4
importlib-metadata==4.12.0
Jinja2==3.1.2
joblib==1.2.0
llvmlite==0.39.1
MarkupSafe==2.1.1
matplotlib==3.6.0
mkl-fft==1.3.1
mkl-random @ file:///home/builder/ci_310/mkl_random_1641843545607/work
mkl-service==2.4.0
numba==0.56.2
numpy @ file:///tmp/abs_653_j00fmm/croots/recipe/numpy_and_numpy_base_1659432701727/work
packaging==21.3
(생략)
...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;당연하게도, 이러한 requirements.txt를 기반으로 `pip install -r requirements.txt`를 실행하면 아래와 같은 에러를 만나게 될것이다. (필자는 타사에서 requirements.txt로 배포/전달하여 곤란을 겪은 경험이 있다.)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;62&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zqE6W/btrWCdWuXig/CqaEn8Ll5lkB4WBk3rOcfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zqE6W/btrWCdWuXig/CqaEn8Ll5lkB4WBk3rOcfk/img.png&quot; data-alt=&quot;정상적인 포맷이 아닌 requirements.txt를 사용하여 패키지 설치. 당연하게도 에러가 발생한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zqE6W/btrWCdWuXig/CqaEn8Ll5lkB4WBk3rOcfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzqE6W%2FbtrWCdWuXig%2FCqaEn8Ll5lkB4WBk3rOcfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;836&quot; height=&quot;62&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;62&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정상적인 포맷이 아닌 requirements.txt를 사용하여 패키지 설치. 당연하게도 에러가 발생한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;3. 문제 발생 원인&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제 발생의 원인을 알아보자. (빈번하게 이런 상황이 발생하면, 많이 힘들어 진다.) 정확하지는 않아도 발생하는 케이스를 살펴봄으로써, 정답에 근접한 답을 도출할 수 있다.&amp;nbsp; 우선 두가지 상황을 비교해 보자. 1) venv로 가상환경을 생성한 결과, 2) conda로 가상환경을 생성한 결과.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;1. venv 가상환경&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1674020866718&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python -m venv .venv_test 
source .venv_test/bin/activate
pip freeze&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행결과 : 아무것도 출력 되지 않는다. (목록 없음) --&amp;gt; 당연한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그렇다면, 기본적인 패키지를 하나 (joblib) 설치해 보자.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674021092713&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install joblib&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 결과 :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1674021123858&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;joblib==1.2.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;2. conda 가상환경&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1674020565938&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda create -n test_env python=3.9
conda activate test_env
pip freeze&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 결과 :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1674020610782&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;certifi @ file:///croot/certifi_1671487769961/work/certifi&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;으응.....????&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본적인 패키지 (joblib) 를 하나 설치해 보자.&lt;/h4&gt;
&lt;pre id=&quot;code_1674021261675&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda install joblib&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 결과:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1674021321254&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;joblib @ file:///croot/joblib_1666298844297/work&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;네 이놈......... 잡았다 !!!&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;확실하게 conda로 패키지를 설치하고, pip freeze의 결과는 그 포맷이 다름을 알 수 있다.&amp;nbsp; 확실하게 하기 위해서, conda install 을 사용한 joblib를 삭제하고, pip install로 다시 설치해 보자.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674021467570&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda uninstall joblib
pip install joblib
pip freeze&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행 결과 :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1674021488854&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;joblib==1.2.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예상과 같이 `conda install`로 설치한 결과와, `pip install`로 설치하는 결과는 `pip freeze`로 표현한 결과의 포맷이 다르다는 것을 확인 할 수 있다. 즉, `pip freeze`를 통하여 패키지 목록을 추출할 때, conda와 pip 는 다른 포맷으로 목록을 출력해 준다는 사실을 확인했다. 어떻게 보면 너무나도 당연한 결과이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그러나, 많은 개발자/연구자들이, python 가상환경을 생성/관리할 때, conda와 venv, 그리고 pip를 혼용해서 사용한다. 필자의 경우는 대부분 venv/pip를 사용하고 있지만, 경우에 따라서는 conda를 사용하기도 한다. 필자의 경우 conda를 사용하는 경우는, python version을 변경할 때 base에 버전을 추가 설치하기는 번거로울 때 이다. venv는 os에서 지정된 python을 그대로 사용하며, conda의 경우에는 python 버전을 자체로 추가 설치하기 때문에 개별 버전을 따로 지정할 수 있기 때문이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;각설하고, 결국 venv, conda, pip 는 각각 다른 패키지 인것이다. 이것들을 혼용하여 사용한다면 각각의 특징과 출력 결과를 인지하고 있어야 할것이다. 필자 주변에서 venv와 conda install 조합( ^^? )하는 특이한 케이스도 봤는데, 이런 경우 괴랄한 결과가 나오더라.&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;추가적인 PIP 버그 (Ubuntu) : pkg_resources&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;전체적인 맥락과는 다른 이야기 이지만, Ubuntu에서 PIP에 버그가 존재한다. 이 때문에 아래와 같은 불필요한 패키지가 하나 추가 된다. (아래는 PIP freeze 결과중 해당 패키지 라인이다.)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SkE2G/btrW6qOiWsk/uWnlFBorblgJDINlnMGRlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SkE2G/btrW6qOiWsk/uWnlFBorblgJDINlnMGRlK/img.png&quot; data-alt=&quot;pkg_resources==0.0.0&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SkE2G/btrW6qOiWsk/uWnlFBorblgJDINlnMGRlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSkE2G%2FbtrW6qOiWsk%2FuWnlFBorblgJDINlnMGRlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;232&quot; height=&quot;178&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;pkg_resources==0.0.0&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1674614726248&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pkg_resources==0.0.0&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;버전을 보면 알 수 있듯이, 버전 `0.0.0`으로 무엇인가 이상하다. 이것은 Linux/Ubuntu에서 발생하는 PIP 버그로 알려져 있다. (PIP Github issue : &lt;a href=&quot;https://github.com/pypa/pip/issues/4022&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/pypa/pip/issues/4022&lt;/a&gt;)&amp;nbsp; 이러한&amp;nbsp; 이 때문에, `pip install -r requirements.txt`를 실행하면 에러가 발생한다. 해결 방안은 requirements.txt에서 해당 라인을 제거하면 된다. 매번 `pkg_resources==0.0.0`을 제거하기 번거롭다면, `grep -v`를 사용하여 requirements.txt를 생성하면 된다. 해당 명령 내용은 아래 &quot;해결방안&quot;에서 거론한다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;4. 해결 방안&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 문제에서 원인이 밝혀지면, 해결방법은 그다지 어렵지 않다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실은 conda가 되었든, pip 가 되었든, 다음과 같이 패키지 리스트와 버전이 출력이 가능하다. (이렇다는 이야기는 단순 포맷팅의 차이라 할 수 있겠다. )&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;pip list&lt;/li&gt;
&lt;li&gt;conda list&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/barYwo/btrWCq9iZzO/ZSHCm7Q7EOgi1Xpdxm95aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/barYwo/btrWCq9iZzO/ZSHCm7Q7EOgi1Xpdxm95aK/img.png&quot; data-origin-width=&quot;221&quot; data-origin-height=&quot;321&quot; data-is-animation=&quot;false&quot; style=&quot;width: 23.627%; margin-right: 10px;&quot; data-widthpercent=&quot;23.9&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/barYwo/btrWCq9iZzO/ZSHCm7Q7EOgi1Xpdxm95aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbarYwo%2FbtrWCq9iZzO%2FZSHCm7Q7EOgi1Xpdxm95aK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;221&quot; height=&quot;321&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSG87V/btrWCenJv8R/v8SEOPChD4nsZC6ByXc7wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSG87V/btrWCenJv8R/v8SEOPChD4nsZC6ByXc7wk/img.png&quot; data-origin-width=&quot;572&quot; data-origin-height=&quot;261&quot; data-is-animation=&quot;false&quot; style=&quot;width: 75.2102%;&quot; data-widthpercent=&quot;76.1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSG87V/btrWCenJv8R/v8SEOPChD4nsZC6ByXc7wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSG87V%2FbtrWCenJv8R%2Fv8SEOPChD4nsZC6ByXc7wk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;572&quot; height=&quot;261&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;pip list 실행 결과 (좌), conda list 실행 결과 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;`conda list`의 경우는 상단에 package 환경에 대한 위치와 가상환경 이름이 같이 출력되고 있다. 사실, 이러한 환경 정보를 활용하여 가상환경을 재현하는 방법이 별도로 존재한다. 아래는 conda를 이용하여 패키지 설치 목록을 생성하고, 이를 통하여 배포/재설치하는 명령이다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[설치 패키지 목록 생성]&lt;/p&gt;
&lt;pre id=&quot;code_1674022573392&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda env export &amp;gt; conda_requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[conda 가상환경 생성 및 패키지 재설치]&lt;/p&gt;
&lt;pre id=&quot;code_1674022677810&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda env create -f conda_requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;conda_requirements.txt에는 가상환경에 대한 정보도 포함되어 있기 때문에, 가상환경 이름을 포함하여 동일한 환경을 재구축한다.&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이러한 패키지를 관리하는 포맷이 다르기 때문에, pip 중심의 requirements.txt와는 거리가 있다. 따라서, 해결 방법은 이러한 포맷을 동일하게 맞추어 주면 된다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;생각외로 해결 방법은 단순하다.&amp;nbsp; `pip freeze` 대신 `pip list`를 사용하고, 포맷은 freeze 형태로 지정해 주면 된다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674018698083&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip list --format=freeze &amp;gt; requirement_pip_list.txt&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위 명령어를 사용하면, conda install을 사용하였거나, pip install을 사용한것과 무관하게 동일한 포맷으로 패키지 목록을 추출할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이제 이전 섹션에서 언급한 `pkg_resources=0.0.0`을 제거해 보자.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674615034193&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip list --format=freeze | grep -v pkg_resources &amp;gt; requirement_pip_list.txt&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;`grep -v &quot;문자열&quot;` 은 인버스 매칭이다. 해당 문자열/조건에 매칭되지 않는 라인만을 출력한다. 상세 내용은 `grep --help`를 참조하기 바란다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;혹은 `pip freeze`에 문제가 없다면 바로 다음과 같이 표현 해도 될것이다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1674615132813&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip freeze | grep -v &quot;pkg_resources&quot; &amp;gt; requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 이야기/Python</category>
      <category>conda</category>
      <category>pip</category>
      <category>pip freeze</category>
      <category>pkg_resources</category>
      <category>python 배포</category>
      <category>python 배포 에러</category>
      <category>python 패키지 리스트</category>
      <category>requirements.txt</category>
      <category>가상환경 관리</category>
      <category>파이썬 설치 목록</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/216</guid>
      <comments>https://windflex.tistory.com/216#entry216comment</comments>
      <pubDate>Wed, 18 Jan 2023 16:09:46 +0900</pubDate>
    </item>
    <item>
      <title>[줌/구글미트] 온라인 회의 가상 배경 사진 모음-1</title>
      <link>https://windflex.tistory.com/215</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;온라인 회의를 진행하다 보면, 배경 (가상 배경) 화면을 새롭게 설정하거나, 변경하고 싶은 경우가 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;또한, 회의 성격에 따라서 그에 걸맞게 변경하면, 센스가 남달라 보이기도 한다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;줌 또는 구글미트에서는 기본 배경을 제공하지만, 너무 식상하기도 하다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이러한 이유로 온라인 가상 배경을 모아 두고자 하는 Needs 생겼다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;모아 두었던 배경 이미지를 공유해 본다.&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_01.jpeg&quot; data-origin-width=&quot;8256&quot; data-origin-height=&quot;5504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2m6Wr/btrWBciJRZA/nOovbddzelRAqXjpc9ik71/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2m6Wr/btrWBciJRZA/nOovbddzelRAqXjpc9ik71/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2m6Wr/btrWBciJRZA/nOovbddzelRAqXjpc9ik71/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2m6Wr%2FbtrWBciJRZA%2FnOovbddzelRAqXjpc9ik71%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;8256&quot; height=&quot;5504&quot; data-filename=&quot;배경이미지_01.jpeg&quot; data-origin-width=&quot;8256&quot; data-origin-height=&quot;5504&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_02.jpeg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSo14r/btrWzP8714f/8IJt4VK9E2VGEL0Vvb9Af0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSo14r/btrWzP8714f/8IJt4VK9E2VGEL0Vvb9Af0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSo14r/btrWzP8714f/8IJt4VK9E2VGEL0Vvb9Af0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSo14r%2FbtrWzP8714f%2F8IJt4VK9E2VGEL0Vvb9Af0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;6016&quot; height=&quot;4016&quot; data-filename=&quot;배경이미지_02.jpeg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_03.jpeg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bivZLP/btrWx5EELZn/S9vBtal5S9kWX9ccJpkcKK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bivZLP/btrWx5EELZn/S9vBtal5S9kWX9ccJpkcKK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bivZLP/btrWx5EELZn/S9vBtal5S9kWX9ccJpkcKK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbivZLP%2FbtrWx5EELZn%2FS9vBtal5S9kWX9ccJpkcKK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4032&quot; height=&quot;3024&quot; data-filename=&quot;배경이미지_03.jpeg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_04.jpeg&quot; data-origin-width=&quot;5184&quot; data-origin-height=&quot;2836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FgEID/btrWwoSI00P/MQBOUkaiLvFc3PJXh03pgk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FgEID/btrWwoSI00P/MQBOUkaiLvFc3PJXh03pgk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FgEID/btrWwoSI00P/MQBOUkaiLvFc3PJXh03pgk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFgEID%2FbtrWwoSI00P%2FMQBOUkaiLvFc3PJXh03pgk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;5184&quot; height=&quot;2836&quot; data-filename=&quot;배경이미지_04.jpeg&quot; data-origin-width=&quot;5184&quot; data-origin-height=&quot;2836&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_05.jpeg&quot; data-origin-width=&quot;3499&quot; data-origin-height=&quot;2324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8FMuX/btrWBhxwTwr/4XYg19yb4pk9xJXmx0JE9K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8FMuX/btrWBhxwTwr/4XYg19yb4pk9xJXmx0JE9K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8FMuX/btrWBhxwTwr/4XYg19yb4pk9xJXmx0JE9K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8FMuX%2FbtrWBhxwTwr%2F4XYg19yb4pk9xJXmx0JE9K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3499&quot; height=&quot;2324&quot; data-filename=&quot;배경이미지_05.jpeg&quot; data-origin-width=&quot;3499&quot; data-origin-height=&quot;2324&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_06.jpeg&quot; data-origin-width=&quot;5813&quot; data-origin-height=&quot;3707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x5wIE/btrWwIQTWai/5XKXLZSx26QCmXsCJacS4K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x5wIE/btrWwIQTWai/5XKXLZSx26QCmXsCJacS4K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x5wIE/btrWwIQTWai/5XKXLZSx26QCmXsCJacS4K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx5wIE%2FbtrWwIQTWai%2F5XKXLZSx26QCmXsCJacS4K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;5813&quot; height=&quot;3707&quot; data-filename=&quot;배경이미지_06.jpeg&quot; data-origin-width=&quot;5813&quot; data-origin-height=&quot;3707&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_07.jpeg&quot; data-origin-width=&quot;5472&quot; data-origin-height=&quot;3648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfBmwJ/btrWzQGZXQU/O88qLi9yewRW1K0WUwUNHk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfBmwJ/btrWzQGZXQU/O88qLi9yewRW1K0WUwUNHk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfBmwJ/btrWzQGZXQU/O88qLi9yewRW1K0WUwUNHk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfBmwJ%2FbtrWzQGZXQU%2FO88qLi9yewRW1K0WUwUNHk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;5472&quot; height=&quot;3648&quot; data-filename=&quot;배경이미지_07.jpeg&quot; data-origin-width=&quot;5472&quot; data-origin-height=&quot;3648&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_08.jpeg&quot; data-origin-width=&quot;4240&quot; data-origin-height=&quot;2832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F9CCH/btrWyNKugoX/RdwIR62YVC38LK4Zykknm0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F9CCH/btrWyNKugoX/RdwIR62YVC38LK4Zykknm0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F9CCH/btrWyNKugoX/RdwIR62YVC38LK4Zykknm0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF9CCH%2FbtrWyNKugoX%2FRdwIR62YVC38LK4Zykknm0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4240&quot; height=&quot;2832&quot; data-filename=&quot;배경이미지_08.jpeg&quot; data-origin-width=&quot;4240&quot; data-origin-height=&quot;2832&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배경이미지_09.jpeg&quot; data-origin-width=&quot;6000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDHFsL/btrWCzRXchf/5jkf55K8xq50QWLTyWezK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDHFsL/btrWCzRXchf/5jkf55K8xq50QWLTyWezK1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDHFsL/btrWCzRXchf/5jkf55K8xq50QWLTyWezK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDHFsL%2FbtrWCzRXchf%2F5jkf55K8xq50QWLTyWezK1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;6000&quot; height=&quot;4000&quot; data-filename=&quot;배경이미지_09.jpeg&quot; data-origin-width=&quot;6000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;온라인_배경이미지.jpeg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rxBd7/btrWwKVxbxr/2DHKmG2h1vl3D9O3tLOY30/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rxBd7/btrWwKVxbxr/2DHKmG2h1vl3D9O3tLOY30/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rxBd7/btrWwKVxbxr/2DHKmG2h1vl3D9O3tLOY30/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrxBd7%2FbtrWwKVxbxr%2F2DHKmG2h1vl3D9O3tLOY30%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;6016&quot; height=&quot;4016&quot; data-filename=&quot;온라인_배경이미지.jpeg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 거실 1.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;996&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RU1sQ/btrWxrOFDea/1QYKPJE1YmNnDMSKow7zc0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RU1sQ/btrWxrOFDea/1QYKPJE1YmNnDMSKow7zc0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RU1sQ/btrWxrOFDea/1QYKPJE1YmNnDMSKow7zc0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRU1sQ%2FbtrWxrOFDea%2F1QYKPJE1YmNnDMSKow7zc0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;996&quot; data-filename=&quot;줌 배경화면 거실 1.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;996&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 거실 3 .jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q5ywi/btrWxppMt67/qLYrK8YNrkIzae2AIWqoT0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q5ywi/btrWxppMt67/qLYrK8YNrkIzae2AIWqoT0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q5ywi/btrWxppMt67/qLYrK8YNrkIzae2AIWqoT0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq5ywi%2FbtrWxppMt67%2FqLYrK8YNrkIzae2AIWqoT0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;1000&quot; data-filename=&quot;줌 배경화면 거실 3 .jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 거실 4.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;852&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceXtVQ/btrWBhYCnIw/WKLChD4d67BsvYsXmpqOu1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceXtVQ/btrWBhYCnIw/WKLChD4d67BsvYsXmpqOu1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceXtVQ/btrWBhYCnIw/WKLChD4d67BsvYsXmpqOu1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceXtVQ%2FbtrWBhYCnIw%2FWKLChD4d67BsvYsXmpqOu1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;852&quot; data-filename=&quot;줌 배경화면 거실 4.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;852&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 거실 5.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;938&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bk2MvQ/btrWxqoFhG8/77E1cYEjK4blo4xbEF5gDK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bk2MvQ/btrWxqoFhG8/77E1cYEjK4blo4xbEF5gDK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bk2MvQ/btrWxqoFhG8/77E1cYEjK4blo4xbEF5gDK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbk2MvQ%2FbtrWxqoFhG8%2F77E1cYEjK4blo4xbEF5gDK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;938&quot; data-filename=&quot;줌 배경화면 거실 5.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;938&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 거실 6.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;844&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZEl8a/btrWw82YhEf/cGdwBUNRuEtAZ8vZlaY9B0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZEl8a/btrWw82YhEf/cGdwBUNRuEtAZ8vZlaY9B0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZEl8a/btrWw82YhEf/cGdwBUNRuEtAZ8vZlaY9B0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZEl8a%2FbtrWw82YhEf%2FcGdwBUNRuEtAZ8vZlaY9B0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;844&quot; data-filename=&quot;줌 배경화면 거실 6.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;844&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 거실 7.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5K1IB/btrWx7PWJor/OkpPkv64WikpdBoLijnNz0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5K1IB/btrWx7PWJor/OkpPkv64WikpdBoLijnNz0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5K1IB/btrWx7PWJor/OkpPkv64WikpdBoLijnNz0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5K1IB%2FbtrWx7PWJor%2FOkpPkv64WikpdBoLijnNz0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;900&quot; data-filename=&quot;줌 배경화면 거실 7.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 거실 8.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfaLJJ/btrWCpICkj1/XNUiw76AcWhJb6iCLCIzBK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfaLJJ/btrWCpICkj1/XNUiw76AcWhJb6iCLCIzBK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfaLJJ/btrWCpICkj1/XNUiw76AcWhJb6iCLCIzBK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfaLJJ%2FbtrWCpICkj1%2FXNUiw76AcWhJb6iCLCIzBK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;1000&quot; data-filename=&quot;줌 배경화면 거실 8.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 거실2.jpg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUcuOt/btrWwJCe9of/6j7dvAJKSAgeCR93tOEcFK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUcuOt/btrWwJCe9of/6j7dvAJKSAgeCR93tOEcFK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUcuOt/btrWwJCe9of/6j7dvAJKSAgeCR93tOEcFK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUcuOt%2FbtrWwJCe9of%2F6j7dvAJKSAgeCR93tOEcFK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1000&quot; height=&quot;562&quot; data-filename=&quot;줌 배경화면 거실2.jpg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 방 3.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSoXHC/btrWwIwDc5J/RNemfXhaioE8mfxUibABY0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSoXHC/btrWwIwDc5J/RNemfXhaioE8mfxUibABY0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSoXHC/btrWwIwDc5J/RNemfXhaioE8mfxUibABY0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSoXHC%2FbtrWwIwDc5J%2FRNemfXhaioE8mfxUibABY0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;1000&quot; data-filename=&quot;줌 배경화면 방 3.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 방 4.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bR20dk/btrWBbKR5XD/qP6jYh64r2rtperow0F5R0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bR20dk/btrWBbKR5XD/qP6jYh64r2rtperow0F5R0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bR20dk/btrWBbKR5XD/qP6jYh64r2rtperow0F5R0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbR20dk%2FbtrWBbKR5XD%2FqP6jYh64r2rtperow0F5R0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;1000&quot; data-filename=&quot;줌 배경화면 방 4.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 방 5.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;839&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cummNY/btrWx7PWJFV/Np28a08aG7EOU6TnmoszaK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cummNY/btrWx7PWJFV/Np28a08aG7EOU6TnmoszaK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cummNY/btrWx7PWJFV/Np28a08aG7EOU6TnmoszaK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcummNY%2FbtrWx7PWJFV%2FNp28a08aG7EOU6TnmoszaK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;839&quot; data-filename=&quot;줌 배경화면 방 5.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;839&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 방 6.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;866&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yeft1/btrWx6csHUx/WKC7ZV4FWNjvm9lhtMPRk0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yeft1/btrWx6csHUx/WKC7ZV4FWNjvm9lhtMPRk0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yeft1/btrWx6csHUx/WKC7ZV4FWNjvm9lhtMPRk0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyeft1%2FbtrWx6csHUx%2FWKC7ZV4FWNjvm9lhtMPRk0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;866&quot; data-filename=&quot;줌 배경화면 방 6.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;866&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 방 7.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;971&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9tRTH/btrWxqPI4pe/ul9uHJCuFh7AA1GNF2R1Q0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9tRTH/btrWxqPI4pe/ul9uHJCuFh7AA1GNF2R1Q0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9tRTH/btrWxqPI4pe/ul9uHJCuFh7AA1GNF2R1Q0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9tRTH%2FbtrWxqPI4pe%2Ful9uHJCuFh7AA1GNF2R1Q0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;971&quot; data-filename=&quot;줌 배경화면 방 7.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;971&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 방 8.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;849&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bg840i/btrWyM5TTIJ/e1iNmZMkH3K2P8eMkYYBKk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bg840i/btrWyM5TTIJ/e1iNmZMkH3K2P8eMkYYBKk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bg840i/btrWyM5TTIJ/e1iNmZMkH3K2P8eMkYYBKk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbg840i%2FbtrWyM5TTIJ%2Fe1iNmZMkH3K2P8eMkYYBKk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;849&quot; data-filename=&quot;줌 배경화면 방 8.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;849&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 방.jpg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;525&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nNojg/btrWCz5uDdi/Af9yMkQltZNtUQ6DoSUjyk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nNojg/btrWCz5uDdi/Af9yMkQltZNtUQ6DoSUjyk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nNojg/btrWCz5uDdi/Af9yMkQltZNtUQ6DoSUjyk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnNojg%2FbtrWCz5uDdi%2FAf9yMkQltZNtUQ6DoSUjyk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1000&quot; height=&quot;525&quot; data-filename=&quot;줌 배경화면 방.jpg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;525&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;줌 배경화면 방2.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1002&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJLjR7/btrWyNjpKlx/px7DNkci8ndvs6aHAwv4A0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJLjR7/btrWyNjpKlx/px7DNkci8ndvs6aHAwv4A0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJLjR7/btrWyNjpKlx/px7DNkci8ndvs6aHAwv4A0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJLjR7%2FbtrWyNjpKlx%2Fpx7DNkci8ndvs6aHAwv4A0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1500&quot; height=&quot;1002&quot; data-filename=&quot;줌 배경화면 방2.jpg&quot; data-origin-width=&quot;1500&quot; data-origin-height=&quot;1002&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;aaron-huber-s95oB2n9jng-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clmxLt/btrWyLy63eX/cJ2k8YOX1au16pT7h07lcK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clmxLt/btrWyLy63eX/cJ2k8YOX1au16pT7h07lcK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clmxLt/btrWyLy63eX/cJ2k8YOX1au16pT7h07lcK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclmxLt%2FbtrWyLy63eX%2FcJ2k8YOX1au16pT7h07lcK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1590&quot; data-filename=&quot;aaron-huber-s95oB2n9jng-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1590&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;adolfo-felix-PG8NyM_Mcts-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q670J/btrWzQNMqe3/D9rudYgpJTSWeV3UVaaZU1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q670J/btrWzQNMqe3/D9rudYgpJTSWeV3UVaaZU1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q670J/btrWzQNMqe3/D9rudYgpJTSWeV3UVaaZU1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq670J%2FbtrWzQNMqe3%2FD9rudYgpJTSWeV3UVaaZU1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;adolfo-felix-PG8NyM_Mcts-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;alberto-castillo-q-mx4mSkK9zeo-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgL4AF/btrWBcC2d7n/fuouhjpOqcfdU77evdpQdK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgL4AF/btrWBcC2d7n/fuouhjpOqcfdU77evdpQdK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgL4AF/btrWBcC2d7n/fuouhjpOqcfdU77evdpQdK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgL4AF%2FbtrWBcC2d7n%2FfuouhjpOqcfdU77evdpQdK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1526&quot; data-filename=&quot;alberto-castillo-q-mx4mSkK9zeo-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1526&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;aleksei-ieshkin-A6obuTm7_z0-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1607&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qldCG/btrWBcC2fg1/u6XKmJHFXmaJaHO2WyihVk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qldCG/btrWBcC2fg1/u6XKmJHFXmaJaHO2WyihVk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qldCG/btrWBcC2fg1/u6XKmJHFXmaJaHO2WyihVk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqldCG%2FbtrWBcC2fg1%2Fu6XKmJHFXmaJaHO2WyihVk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1607&quot; data-filename=&quot;aleksei-ieshkin-A6obuTm7_z0-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1607&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;alesia-kazantceva-VWcPlbHglYc-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IvmaT/btrWwIpRBNZ/6KnSPg6gMM1SuAMvUery10/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IvmaT/btrWwIpRBNZ/6KnSPg6gMM1SuAMvUery10/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IvmaT/btrWwIpRBNZ/6KnSPg6gMM1SuAMvUery10/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIvmaT%2FbtrWwIpRBNZ%2F6KnSPg6gMM1SuAMvUery10%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;alesia-kazantceva-VWcPlbHglYc-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;alessandra-caretto-o3c-euNd_ZM-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDoO4A/btrWxppNT7E/VJPp0Y82aOKZ6370GTZVI0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDoO4A/btrWxppNT7E/VJPp0Y82aOKZ6370GTZVI0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDoO4A/btrWxppNT7E/VJPp0Y82aOKZ6370GTZVI0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDoO4A%2FbtrWxppNT7E%2FVJPp0Y82aOKZ6370GTZVI0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1602&quot; data-filename=&quot;alessandra-caretto-o3c-euNd_ZM-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;alexandra-gorn-JIUjvqe2ZHg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFZVQD/btrWCiiFKQw/vxoG2ONrzR4SUzdVkCaKWk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFZVQD/btrWCiiFKQw/vxoG2ONrzR4SUzdVkCaKWk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFZVQD/btrWCiiFKQw/vxoG2ONrzR4SUzdVkCaKWk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFZVQD%2FbtrWCiiFKQw%2FvxoG2ONrzR4SUzdVkCaKWk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1602&quot; data-filename=&quot;alexandra-gorn-JIUjvqe2ZHg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;amber-eve-anderson-5__ySAG2BWY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsIFOe/btrWw7waOAb/qmoCOMDiE7DvPEKra24zo1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsIFOe/btrWw7waOAb/qmoCOMDiE7DvPEKra24zo1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsIFOe/btrWw7waOAb/qmoCOMDiE7DvPEKra24zo1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsIFOe%2FbtrWw7waOAb%2FqmoCOMDiE7DvPEKra24zo1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;amber-eve-anderson-5__ySAG2BWY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;andrej-lisakov-3A4XZUopCJA-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8Quvx/btrWyNX2vT9/iWaIS9dBeckqap7FDU9yyk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8Quvx/btrWyNX2vT9/iWaIS9dBeckqap7FDU9yyk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8Quvx/btrWyNX2vT9/iWaIS9dBeckqap7FDU9yyk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8Quvx%2FbtrWyNX2vT9%2FiWaIS9dBeckqap7FDU9yyk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1650&quot; data-filename=&quot;andrej-lisakov-3A4XZUopCJA-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1650&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;annie-spratt-FSFfEQkd1sc-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwShq2/btrWxr81Clx/TKgdeuCRlwV94hZqukIlvK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwShq2/btrWxr81Clx/TKgdeuCRlwV94hZqukIlvK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwShq2/btrWxr81Clx/TKgdeuCRlwV94hZqukIlvK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwShq2%2FbtrWxr81Clx%2FTKgdeuCRlwV94hZqukIlvK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1598&quot; data-filename=&quot;annie-spratt-FSFfEQkd1sc-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;annie-spratt-OTy0mkqc2Yk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y5EBW/btrWwKablIS/7v2GF9lUS74TxNTKqh9Jxk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y5EBW/btrWwKablIS/7v2GF9lUS74TxNTKqh9Jxk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y5EBW/btrWwKablIS/7v2GF9lUS74TxNTKqh9Jxk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy5EBW%2FbtrWwKablIS%2F7v2GF9lUS74TxNTKqh9Jxk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1556&quot; data-filename=&quot;annie-spratt-OTy0mkqc2Yk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bckfwd-oB1EJLokN3E-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6rMhx/btrWzVaqIOS/GQ8HtYjdds4WhqaP298CM1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6rMhx/btrWzVaqIOS/GQ8HtYjdds4WhqaP298CM1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6rMhx/btrWzVaqIOS/GQ8HtYjdds4WhqaP298CM1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6rMhx%2FbtrWzVaqIOS%2FGQ8HtYjdds4WhqaP298CM1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;3200&quot; data-filename=&quot;bckfwd-oB1EJLokN3E-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;benjamin-child-0sT9YhNgSEs-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQ358/btrWCq1QJla/8hUjUwiPu6lv8HWGFbL9kk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQ358/btrWCq1QJla/8hUjUwiPu6lv8HWGFbL9kk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQ358/btrWCq1QJla/8hUjUwiPu6lv8HWGFbL9kk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQ358%2FbtrWCq1QJla%2F8hUjUwiPu6lv8HWGFbL9kk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;benjamin-child-0sT9YhNgSEs-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;chastity-cortijo-98WE9hWWjiQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lvi9X/btrWw82Z5e1/vHC9p2F9CurN9zyn4oIO01/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lvi9X/btrWw82Z5e1/vHC9p2F9CurN9zyn4oIO01/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lvi9X/btrWw82Z5e1/vHC9p2F9CurN9zyn4oIO01/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flvi9X%2FbtrWw82Z5e1%2FvHC9p2F9CurN9zyn4oIO01%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1590&quot; data-filename=&quot;chastity-cortijo-98WE9hWWjiQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1590&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;clay-banks-z_DkoUqgx6M-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zx8P5/btrWxs1c3SO/DRFZv4ERvQqCHY52EhErhk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zx8P5/btrWxs1c3SO/DRFZv4ERvQqCHY52EhErhk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zx8P5/btrWxs1c3SO/DRFZv4ERvQqCHY52EhErhk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzx8P5%2FbtrWxs1c3SO%2FDRFZv4ERvQqCHY52EhErhk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1602&quot; data-filename=&quot;clay-banks-z_DkoUqgx6M-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;copernico-p_kICQCOM4s-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xADrq/btrWBbxn5bc/pNKRwYTkrKkDKLxxRRx7c0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xADrq/btrWBbxn5bc/pNKRwYTkrKkDKLxxRRx7c0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xADrq/btrWBbxn5bc/pNKRwYTkrKkDKLxxRRx7c0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxADrq%2FbtrWBbxn5bc%2FpNKRwYTkrKkDKLxxRRx7c0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;copernico-p_kICQCOM4s-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;crew-9u2GMRE8MdE-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1751&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U8YCr/btrWCciuHcU/6xpnOJV1BzBqAmETwkT3YK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U8YCr/btrWCciuHcU/6xpnOJV1BzBqAmETwkT3YK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U8YCr/btrWCciuHcU/6xpnOJV1BzBqAmETwkT3YK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU8YCr%2FbtrWCciuHcU%2F6xpnOJV1BzBqAmETwkT3YK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1751&quot; data-filename=&quot;crew-9u2GMRE8MdE-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1751&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;croissant--BiyRLfotEQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q1O9F/btrWwLNHuWy/SQs4jMkM5vmYektkdnA1Y1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q1O9F/btrWwLNHuWy/SQs4jMkM5vmYektkdnA1Y1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q1O9F/btrWwLNHuWy/SQs4jMkM5vmYektkdnA1Y1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ1O9F%2FbtrWwLNHuWy%2FSQs4jMkM5vmYektkdnA1Y1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;croissant--BiyRLfotEQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;croissant-CW88ysx7Amk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kLFEI/btrWyKttmwx/kYAqmX2iEKQg89vwndk7d1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kLFEI/btrWyKttmwx/kYAqmX2iEKQg89vwndk7d1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kLFEI/btrWyKttmwx/kYAqmX2iEKQg89vwndk7d1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkLFEI%2FbtrWyKttmwx%2FkYAqmX2iEKQg89vwndk7d1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;croissant-CW88ysx7Amk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;daniel-mccullough-FwjWUGbrxOU-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brVx3H/btrWx6Kl0Gx/CwoIiAGTAVTBMIogtKet40/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brVx3H/btrWx6Kl0Gx/CwoIiAGTAVTBMIogtKet40/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brVx3H/btrWx6Kl0Gx/CwoIiAGTAVTBMIogtKet40/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrVx3H%2FbtrWx6Kl0Gx%2FCwoIiAGTAVTBMIogtKet40%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1856&quot; data-filename=&quot;daniel-mccullough-FwjWUGbrxOU-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1856&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;dave-webb-Ny7UDRl2LZY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blOW7E/btrWChxhIPQ/SokGx0evmd3f7Uecawekbk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blOW7E/btrWChxhIPQ/SokGx0evmd3f7Uecawekbk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blOW7E/btrWChxhIPQ/SokGx0evmd3f7Uecawekbk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblOW7E%2FbtrWChxhIPQ%2FSokGx0evmd3f7Uecawekbk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;dave-webb-Ny7UDRl2LZY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;david-fintz-z-Jaxjj0KVY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v87Wz/btrWyKttmQy/8tLfGpkVNrZ8RkbDPkooqk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v87Wz/btrWyKttmQy/8tLfGpkVNrZ8RkbDPkooqk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v87Wz/btrWyKttmQy/8tLfGpkVNrZ8RkbDPkooqk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv87Wz%2FbtrWyKttmQy%2F8tLfGpkVNrZ8RkbDPkooqk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1670&quot; data-filename=&quot;david-fintz-z-Jaxjj0KVY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1670&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;david-pisnoy-46juD4zY1XA-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbBchk/btrWx5klQP0/5SMGwZeaSZeuRfjhxj7SdK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbBchk/btrWx5klQP0/5SMGwZeaSZeuRfjhxj7SdK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbBchk/btrWx5klQP0/5SMGwZeaSZeuRfjhxj7SdK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbBchk%2FbtrWx5klQP0%2F5SMGwZeaSZeuRfjhxj7SdK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;3200&quot; data-filename=&quot;david-pisnoy-46juD4zY1XA-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;david-van-dijk-3LTht2nxd34-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1607&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkyDoO/btrWCpBStC2/PFcsAPCQCiXuwjME1VfeWK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkyDoO/btrWCpBStC2/PFcsAPCQCiXuwjME1VfeWK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkyDoO/btrWCpBStC2/PFcsAPCQCiXuwjME1VfeWK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkyDoO%2FbtrWCpBStC2%2FPFcsAPCQCiXuwjME1VfeWK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1607&quot; data-filename=&quot;david-van-dijk-3LTht2nxd34-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1607&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;deborah-cortelazzi-gREquCUXQLI-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WplxH/btrWBhK66cR/J8KUAsbJbT8BKsr3XJegpK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WplxH/btrWBhK66cR/J8KUAsbJbT8BKsr3XJegpK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WplxH/btrWBhK66cR/J8KUAsbJbT8BKsr3XJegpK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWplxH%2FbtrWBhK66cR%2FJ8KUAsbJbT8BKsr3XJegpK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;deborah-cortelazzi-gREquCUXQLI-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;dell-g2E2NQ5SWSU-unsplash (1).jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZfo27/btrWx73yAHH/4bWk4vKhfvz0nO4HEqN5fk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZfo27/btrWx73yAHH/4bWk4vKhfvz0nO4HEqN5fk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZfo27/btrWx73yAHH/4bWk4vKhfvz0nO4HEqN5fk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZfo27%2FbtrWx73yAHH%2F4bWk4vKhfvz0nO4HEqN5fk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1602&quot; data-filename=&quot;dell-g2E2NQ5SWSU-unsplash (1).jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;dell-g2E2NQ5SWSU-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIZXyz/btrWCqnfd6f/YKcJQp0uSOD0GkIKiLL6c0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIZXyz/btrWCqnfd6f/YKcJQp0uSOD0GkIKiLL6c0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIZXyz/btrWCqnfd6f/YKcJQp0uSOD0GkIKiLL6c0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIZXyz%2FbtrWCqnfd6f%2FYKcJQp0uSOD0GkIKiLL6c0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1602&quot; data-filename=&quot;dell-g2E2NQ5SWSU-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;dmytro-tolokonov-Jq3WI9IQgEs-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;2400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj4fBl/btrWzUCCMIb/vDmnsieRQIIE4cqIsFu9J0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj4fBl/btrWzUCCMIb/vDmnsieRQIIE4cqIsFu9J0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj4fBl/btrWzUCCMIb/vDmnsieRQIIE4cqIsFu9J0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj4fBl%2FbtrWzUCCMIb%2FvDmnsieRQIIE4cqIsFu9J0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;2400&quot; data-filename=&quot;dmytro-tolokonov-Jq3WI9IQgEs-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;2400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;donnie-rosie-taO2fC7sxDU-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G4BOd/btrWCcCM3vx/KXjYDGMCYfkCWA21mUAlOk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G4BOd/btrWCcCM3vx/KXjYDGMCYfkCWA21mUAlOk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G4BOd/btrWCcCM3vx/KXjYDGMCYfkCWA21mUAlOk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG4BOd%2FbtrWCcCM3vx%2FKXjYDGMCYfkCWA21mUAlOk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;donnie-rosie-taO2fC7sxDU-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;drew-coffman-jUOaONoXJQk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cACu3v/btrWyMdJ7D9/x2I8vmwVQWvd4UzvhrOhK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cACu3v/btrWyMdJ7D9/x2I8vmwVQWvd4UzvhrOhK1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cACu3v/btrWyMdJ7D9/x2I8vmwVQWvd4UzvhrOhK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcACu3v%2FbtrWyMdJ7D9%2Fx2I8vmwVQWvd4UzvhrOhK1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;drew-coffman-jUOaONoXJQk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;elsa-noblet-5KD5PmZEfcg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/plzcD/btrWxppNVyn/CKak4kFpIr4VDWy1SkFea1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/plzcD/btrWxppNVyn/CKak4kFpIr4VDWy1SkFea1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/plzcD/btrWxppNVyn/CKak4kFpIr4VDWy1SkFea1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FplzcD%2FbtrWxppNVyn%2FCKak4kFpIr4VDWy1SkFea1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;elsa-noblet-5KD5PmZEfcg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;goran-ivos-d74sP6dnt_I-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1837&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTjOpj/btrWCyrZ93N/oA7gSucKikTIB6TjLDq5B1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTjOpj/btrWCyrZ93N/oA7gSucKikTIB6TjLDq5B1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTjOpj/btrWCyrZ93N/oA7gSucKikTIB6TjLDq5B1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTjOpj%2FbtrWCyrZ93N%2FoA7gSucKikTIB6TjLDq5B1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1837&quot; data-filename=&quot;goran-ivos-d74sP6dnt_I-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1837&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;greg-rivers-ww8Rll1Vsfc-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yQdE7/btrWzUvQfpj/5VgNJGUvqnFutWr1wivkj1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yQdE7/btrWzUvQfpj/5VgNJGUvqnFutWr1wivkj1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yQdE7/btrWzUvQfpj/5VgNJGUvqnFutWr1wivkj1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyQdE7%2FbtrWzUvQfpj%2F5VgNJGUvqnFutWr1wivkj1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;greg-rivers-ww8Rll1Vsfc-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;helena-hertz-WwD-LlmXp5o-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bI03d2/btrWCgZsjVX/M8Hq88qkUcdLcGyq6grcD1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bI03d2/btrWCgZsjVX/M8Hq88qkUcdLcGyq6grcD1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bI03d2/btrWCgZsjVX/M8Hq88qkUcdLcGyq6grcD1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbI03d2%2FbtrWCgZsjVX%2FM8Hq88qkUcdLcGyq6grcD1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1800&quot; data-filename=&quot;helena-hertz-WwD-LlmXp5o-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;hutomo-abrianto-X5BWooeO4Cw-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBdrKB/btrWCp2Wtxp/UVGIXpMdlhPohC9Hatt27k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBdrKB/btrWCp2Wtxp/UVGIXpMdlhPohC9Hatt27k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBdrKB/btrWCp2Wtxp/UVGIXpMdlhPohC9Hatt27k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBdrKB%2FbtrWCp2Wtxp%2FUVGIXpMdlhPohC9Hatt27k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;3600&quot; data-filename=&quot;hutomo-abrianto-X5BWooeO4Cw-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;huy-phan-EleyBNnodCY-unsplash (1).jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1794&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x8Il7/btrWBbxn6Az/PS1k9IsrkWp9hx34wZFKbK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x8Il7/btrWBbxn6Az/PS1k9IsrkWp9hx34wZFKbK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x8Il7/btrWBbxn6Az/PS1k9IsrkWp9hx34wZFKbK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx8Il7%2FbtrWBbxn6Az%2FPS1k9IsrkWp9hx34wZFKbK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1794&quot; data-filename=&quot;huy-phan-EleyBNnodCY-unsplash (1).jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1794&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;huy-phan-EleyBNnodCY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1794&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceWnAL/btrWBaZxmlR/GDQpxV9keRXUWX8YhumvG0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceWnAL/btrWBaZxmlR/GDQpxV9keRXUWX8YhumvG0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceWnAL/btrWBaZxmlR/GDQpxV9keRXUWX8YhumvG0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceWnAL%2FbtrWBaZxmlR%2FGDQpxV9keRXUWX8YhumvG0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1794&quot; data-filename=&quot;huy-phan-EleyBNnodCY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1794&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;im3rd-media-RTxQBPGA3IQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQzBXP/btrWw6cWYIh/CMjNtOt8J6b6UMdzMAP8Kk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQzBXP/btrWw6cWYIh/CMjNtOt8J6b6UMdzMAP8Kk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQzBXP/btrWw6cWYIh/CMjNtOt8J6b6UMdzMAP8Kk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQzBXP%2FbtrWw6cWYIh%2FCMjNtOt8J6b6UMdzMAP8Kk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;im3rd-media-RTxQBPGA3IQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (1).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doUZm9/btrWw9Oi2Bp/m03gPC2mlUBzBuezL1VIn0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doUZm9/btrWw9Oi2Bp/m03gPC2mlUBzBuezL1VIn0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doUZm9/btrWw9Oi2Bp/m03gPC2mlUBzBuezL1VIn0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdoUZm9%2FbtrWw9Oi2Bp%2Fm03gPC2mlUBzBuezL1VIn0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img (1).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (2).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PKIO9/btrWCpu6XIn/3mozIkSu8mwUoZBUWqTIK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PKIO9/btrWCpu6XIn/3mozIkSu8mwUoZBUWqTIK1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PKIO9/btrWCpu6XIn/3mozIkSu8mwUoZBUWqTIK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPKIO9%2FbtrWCpu6XIn%2F3mozIkSu8mwUoZBUWqTIK1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img (2).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (3).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yieFE/btrWzQmII0U/ewszb1hk0wZTb54jZz8Cok/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yieFE/btrWzQmII0U/ewszb1hk0wZTb54jZz8Cok/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yieFE/btrWzQmII0U/ewszb1hk0wZTb54jZz8Cok/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyieFE%2FbtrWzQmII0U%2Fewszb1hk0wZTb54jZz8Cok%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img (3).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (4).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cX5rkd/btrWwKgXofL/8Nhw1xy4XjPVoxkTl48z21/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cX5rkd/btrWwKgXofL/8Nhw1xy4XjPVoxkTl48z21/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cX5rkd/btrWwKgXofL/8Nhw1xy4XjPVoxkTl48z21/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcX5rkd%2FbtrWwKgXofL%2F8Nhw1xy4XjPVoxkTl48z21%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img (4).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (5).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwYnjM/btrWx8uCyWq/0Cf3nviikSz9metHdLik81/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwYnjM/btrWx8uCyWq/0Cf3nviikSz9metHdLik81/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwYnjM/btrWx8uCyWq/0Cf3nviikSz9metHdLik81/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwYnjM%2FbtrWx8uCyWq%2F0Cf3nviikSz9metHdLik81%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img (5).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (6).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ds262e/btrWyLy7mpc/pKnwMQ7NbzwqSfMKKqkq11/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ds262e/btrWyLy7mpc/pKnwMQ7NbzwqSfMKKqkq11/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ds262e/btrWyLy7mpc/pKnwMQ7NbzwqSfMKKqkq11/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fds262e%2FbtrWyLy7mpc%2FpKnwMQ7NbzwqSfMKKqkq11%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img (6).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (7).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bazz2r/btrWCqguaLF/KsPSsEZ4XrNupwHdAkDC0k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bazz2r/btrWCqguaLF/KsPSsEZ4XrNupwHdAkDC0k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bazz2r/btrWCqguaLF/KsPSsEZ4XrNupwHdAkDC0k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbazz2r%2FbtrWCqguaLF%2FKsPSsEZ4XrNupwHdAkDC0k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img (7).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (8).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GnAba/btrWCyyL9J4/LRt6UvKSw0KxUPA3ARSdZK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GnAba/btrWCyyL9J4/LRt6UvKSw0KxUPA3ARSdZK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GnAba/btrWCyyL9J4/LRt6UvKSw0KxUPA3ARSdZK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGnAba%2FbtrWCyyL9J4%2FLRt6UvKSw0KxUPA3ARSdZK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img (8).jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ngyqS/btrWzUvQxGP/Yja46bqwBqDukEf755HipK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ngyqS/btrWzUvQxGP/Yja46bqwBqDukEf755HipK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ngyqS/btrWzUvQxGP/Yja46bqwBqDukEf755HipK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FngyqS%2FbtrWzUvQxGP%2FYja46bqwBqDukEf755HipK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1600&quot; height=&quot;900&quot; data-filename=&quot;img.jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;inaki-del-olmo-NIJuEQw0RKg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4SYVl/btrWwJbfQ0l/qFpyoLlCXA45lxLnLRgCkK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4SYVl/btrWwJbfQ0l/qFpyoLlCXA45lxLnLRgCkK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4SYVl/btrWwJbfQ0l/qFpyoLlCXA45lxLnLRgCkK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4SYVl%2FbtrWwJbfQ0l%2FqFpyoLlCXA45lxLnLRgCkK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;inaki-del-olmo-NIJuEQw0RKg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;inside-weather-Uxqlfigh6oE-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8v8Bp/btrWCy6B2Sp/JrPHJLtU6e7PSF8i8GfpP0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8v8Bp/btrWCy6B2Sp/JrPHJLtU6e7PSF8i8GfpP0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8v8Bp/btrWCy6B2Sp/JrPHJLtU6e7PSF8i8GfpP0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8v8Bp%2FbtrWCy6B2Sp%2FJrPHJLtU6e7PSF8i8GfpP0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;3600&quot; data-filename=&quot;inside-weather-Uxqlfigh6oE-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;israa-hilles-nphgNqnEyjk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bepjUE/btrWwIQVXJq/KpCyVchGfAwjPQXEUqG191/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bepjUE/btrWwIQVXJq/KpCyVchGfAwjPQXEUqG191/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bepjUE/btrWwIQVXJq/KpCyVchGfAwjPQXEUqG191/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbepjUE%2FbtrWwIQVXJq%2FKpCyVchGfAwjPQXEUqG191%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;israa-hilles-nphgNqnEyjk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;israa-hilles-xP0gM0Dh-MY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oNIDK/btrWBjB8bR0/EvWkSFOQGzQA6RKYCFpE9k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oNIDK/btrWBjB8bR0/EvWkSFOQGzQA6RKYCFpE9k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oNIDK/btrWBjB8bR0/EvWkSFOQGzQA6RKYCFpE9k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoNIDK%2FbtrWBjB8bR0%2FEvWkSFOQGzQA6RKYCFpE9k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;israa-hilles-xP0gM0Dh-MY-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;janko-ferlic-sfL_QOnmy00-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;2219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buLY9z/btrWw9t05bT/EWmNdCj7JtKN6FWmqBeMtk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buLY9z/btrWw9t05bT/EWmNdCj7JtKN6FWmqBeMtk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buLY9z/btrWw9t05bT/EWmNdCj7JtKN6FWmqBeMtk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuLY9z%2FbtrWw9t05bT%2FEWmNdCj7JtKN6FWmqBeMtk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;2219&quot; data-filename=&quot;janko-ferlic-sfL_QOnmy00-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;2219&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;jarek-ceborski-jn7uVeCdf6U-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBg2xo/btrWx8aiVX2/hJljtEb29t9D13tBNu27g1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBg2xo/btrWx8aiVX2/hJljtEb29t9D13tBNu27g1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBg2xo/btrWx8aiVX2/hJljtEb29t9D13tBNu27g1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBg2xo%2FbtrWx8aiVX2%2FhJljtEb29t9D13tBNu27g1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1602&quot; data-filename=&quot;jarek-ceborski-jn7uVeCdf6U-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;jesse-bowser-SpZWvCkjTwc-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQAnY8/btrWzP2qCrk/XYEVpfRusymZ6gjkfYrPNK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQAnY8/btrWzP2qCrk/XYEVpfRusymZ6gjkfYrPNK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQAnY8/btrWzP2qCrk/XYEVpfRusymZ6gjkfYrPNK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQAnY8%2FbtrWzP2qCrk%2FXYEVpfRusymZ6gjkfYrPNK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;3200&quot; data-filename=&quot;jesse-bowser-SpZWvCkjTwc-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;jon-tyson-QL0FAxaq2z0-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3i24z/btrWyOCF8xF/tPRvxfAmjJLDKgTbErz2eK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3i24z/btrWyOCF8xF/tPRvxfAmjJLDKgTbErz2eK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3i24z/btrWyOCF8xF/tPRvxfAmjJLDKgTbErz2eK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3i24z%2FbtrWyOCF8xF%2FtPRvxfAmjJLDKgTbErz2eK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1800&quot; data-filename=&quot;jon-tyson-QL0FAxaq2z0-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;kenny-eliason-Wp7t4cWN-68-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DKwZf/btrWwLNHVyJ/61UXxoqHNswE92clCg5KD1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DKwZf/btrWwLNHVyJ/61UXxoqHNswE92clCg5KD1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DKwZf/btrWwLNHVyJ/61UXxoqHNswE92clCg5KD1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDKwZf%2FbtrWwLNHVyJ%2F61UXxoqHNswE92clCg5KD1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;kenny-eliason-Wp7t4cWN-68-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;lindsey-lamont-fzqmFDwxKkk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SKMpw/btrWzQtsO2Z/KliLQhNenI4M0YLOivzoHK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SKMpw/btrWzQtsO2Z/KliLQhNenI4M0YLOivzoHK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SKMpw/btrWzQtsO2Z/KliLQhNenI4M0YLOivzoHK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSKMpw%2FbtrWzQtsO2Z%2FKliLQhNenI4M0YLOivzoHK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;lindsey-lamont-fzqmFDwxKkk-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;mathew-schwartz-GjzJFMnJZYg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cV9Vrw/btrWxr81U0P/MQG4Ow8NA8DBRvkGGEhZq0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cV9Vrw/btrWxr81U0P/MQG4Ow8NA8DBRvkGGEhZq0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cV9Vrw/btrWxr81U0P/MQG4Ow8NA8DBRvkGGEhZq0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcV9Vrw%2FbtrWxr81U0P%2FMQG4Ow8NA8DBRvkGGEhZq0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;mathew-schwartz-GjzJFMnJZYg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;mike-benna-SBiVq9eWEtQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rKBZ4/btrWw89HsIE/KWS04jXeWp5mTYLkQ3WLd0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rKBZ4/btrWw89HsIE/KWS04jXeWp5mTYLkQ3WLd0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rKBZ4/btrWw89HsIE/KWS04jXeWp5mTYLkQ3WLd0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrKBZ4%2FbtrWw89HsIE%2FKWS04jXeWp5mTYLkQ3WLd0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;mike-benna-SBiVq9eWEtQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;minh-pham-YAPZt8wxMO4-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rMIue/btrWxqCkZzQ/PIUfmV4F1abRq4zGBeYWOk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rMIue/btrWxqCkZzQ/PIUfmV4F1abRq4zGBeYWOk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rMIue/btrWxqCkZzQ/PIUfmV4F1abRq4zGBeYWOk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrMIue%2FbtrWxqCkZzQ%2FPIUfmV4F1abRq4zGBeYWOk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;3600&quot; data-filename=&quot;minh-pham-YAPZt8wxMO4-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;minha-baek-HaU6PimvBQw-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PXGyT/btrWwIclCH7/MrzKk8lFp4Kkm4kr7k6VQK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PXGyT/btrWwIclCH7/MrzKk8lFp4Kkm4kr7k6VQK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PXGyT/btrWwIclCH7/MrzKk8lFp4Kkm4kr7k6VQK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPXGyT%2FbtrWwIclCH7%2FMrzKk8lFp4Kkm4kr7k6VQK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;minha-baek-HaU6PimvBQw-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;mitchell-luo-xREzOtWzDrQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7BF4y/btrWxsNDzte/SvVDn4iX0QP5StP3UVwBK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7BF4y/btrWxsNDzte/SvVDn4iX0QP5StP3UVwBK1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7BF4y/btrWxsNDzte/SvVDn4iX0QP5StP3UVwBK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7BF4y%2FbtrWxsNDzte%2FSvVDn4iX0QP5StP3UVwBK1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;mitchell-luo-xREzOtWzDrQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nastuh-abootalebi-eHD8Y1Znfpk-unsplash.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mskZw/btrWwH5yvU1/c1xRx0aR05xa7B0FLmqqnk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mskZw/btrWwH5yvU1/c1xRx0aR05xa7B0FLmqqnk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mskZw/btrWwH5yvU1/c1xRx0aR05xa7B0FLmqqnk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmskZw%2FbtrWwH5yvU1%2Fc1xRx0aR05xa7B0FLmqqnk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1282&quot; data-filename=&quot;nastuh-abootalebi-eHD8Y1Znfpk-unsplash.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nastuh-abootalebi-rSpMla5RItA-unsplash.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czkRvM/btrWCdV1ztp/OMfQbYzXzdfMxhsGaM7pAk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czkRvM/btrWCdV1ztp/OMfQbYzXzdfMxhsGaM7pAk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czkRvM/btrWCdV1ztp/OMfQbYzXzdfMxhsGaM7pAk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczkRvM%2FbtrWCdV1ztp%2FOMfQbYzXzdfMxhsGaM7pAk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1282&quot; data-filename=&quot;nastuh-abootalebi-rSpMla5RItA-unsplash.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nathan-fertig-FBXuXp57eM0-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coXQsD/btrWzRlBWPZ/yGo9F3xMAPQXe2Ja6xWRIK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coXQsD/btrWzRlBWPZ/yGo9F3xMAPQXe2Ja6xWRIK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coXQsD/btrWzRlBWPZ/yGo9F3xMAPQXe2Ja6xWRIK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoXQsD%2FbtrWzRlBWPZ%2FyGo9F3xMAPQXe2Ja6xWRIK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;nathan-fertig-FBXuXp57eM0-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nathan-van-egmond-9LMRQdVv7hw-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dND2lT/btrWx6cuY4x/KOF9c5YsZiXAR1cHgTnpdK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dND2lT/btrWx6cuY4x/KOF9c5YsZiXAR1cHgTnpdK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dND2lT/btrWx6cuY4x/KOF9c5YsZiXAR1cHgTnpdK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdND2lT%2FbtrWx6cuY4x%2FKOF9c5YsZiXAR1cHgTnpdK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;nathan-van-egmond-9LMRQdVv7hw-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;patrick-perkins-3wylDrjxH-E-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1786&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z3TFC/btrWBb5cnf6/YcIoumXcGIB54G0QHkKcRk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z3TFC/btrWBb5cnf6/YcIoumXcGIB54G0QHkKcRk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z3TFC/btrWBb5cnf6/YcIoumXcGIB54G0QHkKcRk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ3TFC%2FbtrWBb5cnf6%2FYcIoumXcGIB54G0QHkKcRk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1786&quot; data-filename=&quot;patrick-perkins-3wylDrjxH-E-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1786&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;patrick-schneider-brcLcpPf3x4-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2sN7i/btrWwLUv1Hw/linoveave15XQguaDdXBvK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2sN7i/btrWwLUv1Hw/linoveave15XQguaDdXBvK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2sN7i/btrWwLUv1Hw/linoveave15XQguaDdXBvK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2sN7i%2FbtrWwLUv1Hw%2Flinoveave15XQguaDdXBvK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;patrick-schneider-brcLcpPf3x4-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;patrick-tomasso-QMDap1TAu0g-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgtXw1/btrWCcQk0WV/Ql1BPrsGUyadIiJL5wRL6K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgtXw1/btrWCcQk0WV/Ql1BPrsGUyadIiJL5wRL6K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgtXw1/btrWCcQk0WV/Ql1BPrsGUyadIiJL5wRL6K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgtXw1%2FbtrWCcQk0WV%2FQl1BPrsGUyadIiJL5wRL6K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1800&quot; data-filename=&quot;patrick-tomasso-QMDap1TAu0g-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;prudence-earl-NwBx723XaHw-unsplash.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctnRkb/btrWwKabJt3/VNY6z2tdN5XMcJVk6YdpjK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctnRkb/btrWwKabJt3/VNY6z2tdN5XMcJVk6YdpjK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctnRkb/btrWwKabJt3/VNY6z2tdN5XMcJVk6YdpjK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctnRkb%2FbtrWwKabJt3%2FVNY6z2tdN5XMcJVk6YdpjK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1280&quot; data-filename=&quot;prudence-earl-NwBx723XaHw-unsplash.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;raj-rana-zCQsBI7ZltQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uRkdy/btrWCpWbCNC/wBgAxFTF4OriWfUFCg7Js0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uRkdy/btrWCpWbCNC/wBgAxFTF4OriWfUFCg7Js0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uRkdy/btrWCpWbCNC/wBgAxFTF4OriWfUFCg7Js0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuRkdy%2FbtrWCpWbCNC%2FwBgAxFTF4OriWfUFCg7Js0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;raj-rana-zCQsBI7ZltQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ricardo-frantz-sC-BXbi9ajw-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dykUfE/btrWwKH3G5U/UDTbLAUG5BK7nHGgN1kzN0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dykUfE/btrWwKH3G5U/UDTbLAUG5BK7nHGgN1kzN0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dykUfE/btrWwKH3G5U/UDTbLAUG5BK7nHGgN1kzN0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdykUfE%2FbtrWwKH3G5U%2FUDTbLAUG5BK7nHGgN1kzN0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;ricardo-frantz-sC-BXbi9ajw-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;roam-in-color-RryFk4n-vOs-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1581&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tXFAc/btrWx7CtzkL/X72sMNo4tqgeM6hcdnKVlk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tXFAc/btrWx7CtzkL/X72sMNo4tqgeM6hcdnKVlk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tXFAc/btrWx7CtzkL/X72sMNo4tqgeM6hcdnKVlk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtXFAc%2FbtrWx7CtzkL%2FX72sMNo4tqgeM6hcdnKVlk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1581&quot; data-filename=&quot;roam-in-color-RryFk4n-vOs-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1581&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;roberto-nickson-bwIqQ5qQhXs-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WnYBv/btrWCd2MMJF/dkV5ARzYped5HKLP2bGe80/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WnYBv/btrWCd2MMJF/dkV5ARzYped5HKLP2bGe80/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WnYBv/btrWCd2MMJF/dkV5ARzYped5HKLP2bGe80/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWnYBv%2FbtrWCd2MMJF%2FdkV5ARzYped5HKLP2bGe80%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;roberto-nickson-bwIqQ5qQhXs-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;roman-mager-oHrodCLNnU8-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHc3MP/btrWxqoGX09/vX0BRCakuD6zXi2lpkyFi1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHc3MP/btrWxqoGX09/vX0BRCakuD6zXi2lpkyFi1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHc3MP/btrWxqoGX09/vX0BRCakuD6zXi2lpkyFi1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHc3MP%2FbtrWxqoGX09%2FvX0BRCakuD6zXi2lpkyFi1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1776&quot; data-filename=&quot;roman-mager-oHrodCLNnU8-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1776&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;s-o-c-i-a-l-c-u-t-gREi-9tI5Mg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v20e1/btrWBbjRfRD/LyY6ajpt7IXlkZvtCDNRM0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v20e1/btrWBbjRfRD/LyY6ajpt7IXlkZvtCDNRM0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v20e1/btrWBbjRfRD/LyY6ajpt7IXlkZvtCDNRM0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv20e1%2FbtrWBbjRfRD%2FLyY6ajpt7IXlkZvtCDNRM0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;s-o-c-i-a-l-c-u-t-gREi-9tI5Mg-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;s-o-c-i-a-l-c-u-t-ZGqe7DaJn1w-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cj7h5J/btrWChKP4Ez/mT4kfuCgmuEHAX7gNvWjl0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cj7h5J/btrWChKP4Ez/mT4kfuCgmuEHAX7gNvWjl0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cj7h5J/btrWChKP4Ez/mT4kfuCgmuEHAX7gNvWjl0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcj7h5J%2FbtrWChKP4Ez%2FmT4kfuCgmuEHAX7gNvWjl0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;s-o-c-i-a-l-c-u-t-ZGqe7DaJn1w-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;sabri-tuzcu-w8HTBRcsmNo-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnMhj6/btrWBbKT9wy/LEMRqRrkeIga5IK6ilTivk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnMhj6/btrWBbKT9wy/LEMRqRrkeIga5IK6ilTivk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnMhj6/btrWBbKT9wy/LEMRqRrkeIga5IK6ilTivk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnMhj6%2FbtrWBbKT9wy%2FLEMRqRrkeIga5IK6ilTivk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1590&quot; data-filename=&quot;sabri-tuzcu-w8HTBRcsmNo-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1590&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;sarah-dorweiler-x2Tmfd1-SgA-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pHHlT/btrWBiiVbxb/5HjyY8WM4kN5C5addkAIoK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pHHlT/btrWBiiVbxb/5HjyY8WM4kN5C5addkAIoK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pHHlT/btrWBiiVbxb/5HjyY8WM4kN5C5addkAIoK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpHHlT%2FbtrWBiiVbxb%2F5HjyY8WM4kN5C5addkAIoK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1634&quot; data-filename=&quot;sarah-dorweiler-x2Tmfd1-SgA-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;sidekix-media-JXFBzeZwqx8-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdmMUH/btrWCqt00T7/yj4YAPs8zJfWGAaz0PlJW0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdmMUH/btrWCqt00T7/yj4YAPs8zJfWGAaz0PlJW0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdmMUH/btrWCqt00T7/yj4YAPs8zJfWGAaz0PlJW0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdmMUH%2FbtrWCqt00T7%2Fyj4YAPs8zJfWGAaz0PlJW0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;sidekix-media-JXFBzeZwqx8-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;viktor-bystrov-eHRzs3zunvQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lkFzn/btrWxsNDBS8/1ck58cHufz0xXksgxk48Fk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lkFzn/btrWxsNDBS8/1ck58cHufz0xXksgxk48Fk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lkFzn/btrWxsNDBS8/1ck58cHufz0xXksgxk48Fk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlkFzn%2FbtrWxsNDBS8%2F1ck58cHufz0xXksgxk48Fk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;viktor-bystrov-eHRzs3zunvQ-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;yann-maignan-rRiAzFkJPMo-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWlowl/btrWyKAeF7P/FybohPyVaHYhKhuMK29qY0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWlowl/btrWyKAeF7P/FybohPyVaHYhKhuMK29qY0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWlowl/btrWyKAeF7P/FybohPyVaHYhKhuMK29qY0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWlowl%2FbtrWyKAeF7P%2FFybohPyVaHYhKhuMK29qY0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;1600&quot; data-filename=&quot;yann-maignan-rRiAzFkJPMo-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;zoltan-tasi-eS1omi9_W58-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Csc0a/btrWwKONlZY/PFBEL7CYDlLrSKEsyKwVK0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Csc0a/btrWwKONlZY/PFBEL7CYDlLrSKEsyKwVK0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Csc0a/btrWwKONlZY/PFBEL7CYDlLrSKEsyKwVK0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCsc0a%2FbtrWwKONlZY%2FPFBEL7CYDlLrSKEsyKwVK0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2400&quot; height=&quot;3600&quot; data-filename=&quot;zoltan-tasi-eS1omi9_W58-unsplash.jpg&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;3600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처 : unsplash&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>unsplash</category>
      <category>가상 배경화면</category>
      <category>가상배경 변경</category>
      <category>구글미트 배경화면</category>
      <category>배경 변경</category>
      <category>온라인 회의</category>
      <category>온라인 회의 배경 변경</category>
      <category>줌 배경화면</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/215</guid>
      <comments>https://windflex.tistory.com/215#entry215comment</comments>
      <pubDate>Wed, 18 Jan 2023 13:31:24 +0900</pubDate>
    </item>
    <item>
      <title>[Git/Github] Git 브랜치(branch) 이름 변경 master -&amp;gt; main</title>
      <link>https://windflex.tistory.com/214</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 Github의 기본/메인 브랜치는 &quot;master&quot;라는 이름을 사용했으나, 최근에는 &quot;main&quot;으로 변경 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, Git에서는 아직 기본 브랜치 명칭을 &quot;master&quot;로 사용하고 있으며, Cloud / Serverless 등 서비스에 따라서 CI/CD를 적용할 때 브랜치 명이 각각 다르다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 main브랜치 명을 사용하고 있으나, &quot;master&quot;브랜치를 요구하고 있어서 에러가 발생하는 경우이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b43wVe/btrVe32I2wv/NnNaAsMkQ4oZokK1Ak46ZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b43wVe/btrVe32I2wv/NnNaAsMkQ4oZokK1Ak46ZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b43wVe/btrVe32I2wv/NnNaAsMkQ4oZokK1Ak46ZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb43wVe%2FbtrVe32I2wv%2FNnNaAsMkQ4oZokK1Ak46ZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;713&quot; height=&quot;182&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 기본 브랜치 명칭이 달라지는데, 기본 브랜치를 &quot;master&quot;와 &quot;main&quot;으로 2종을 관리하기도 어렵다. 따라서, 기본 브랜치의 명칭 자체를 변경해야 하는 경우도 발생한다. 이런경우, 아래와 같이 브랜치 이름을 변경해 주자. `옵션 -m`&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1672727689668&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git branch -m master main&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1672727704432&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git status&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 브랜치명을 변경하지 않고, 타겟 브랜치에 push를 하기 위해서는 다음과 같이 수행할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1672752757523&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git push origin main:master&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;로컬 리파지토리의 브랜치는 &quot;main&quot; 원격 리파지토리는 &quot;master&quot;인 경우이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>Branch</category>
      <category>branch 이름 변경</category>
      <category>git</category>
      <category>Github</category>
      <category>Main</category>
      <category>Master</category>
      <category>깃허브</category>
      <category>브랜치 이름 변경</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/214</guid>
      <comments>https://windflex.tistory.com/214#entry214comment</comments>
      <pubDate>Thu, 12 Jan 2023 11:20:14 +0900</pubDate>
    </item>
    <item>
      <title>[Azure] Azure 웹앱(App Service)으로 API 서버 만들기 - 1</title>
      <link>https://windflex.tistory.com/213</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EkdIO/btrVyWW5tSa/PL3PTk3J5pIzctApHRd2v1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EkdIO/btrVyWW5tSa/PL3PTk3J5pIzctApHRd2v1/img.png&quot; data-alt=&quot;Azure 웹앱 (App Service)에 Python/Flask API 서버를 만들어 보자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EkdIO/btrVyWW5tSa/PL3PTk3J5pIzctApHRd2v1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEkdIO%2FbtrVyWW5tSa%2FPL3PTk3J5pIzctApHRd2v1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;500&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Azure 웹앱 (App Service)에 Python/Flask API 서버를 만들어 보자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[요약]&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Python/Flask 소스 준비&lt;/li&gt;
&lt;li&gt;Azure Portal에서 App Service 생성 -&amp;gt; 일단 source 는 설정하지 않음&lt;/li&gt;
&lt;li&gt;App Service &amp;gt; 배포센터 &amp;gt; 코드 : Local Git으로 설정&lt;/li&gt;
&lt;li&gt;App Service &amp;gt; 구성 &amp;gt; LocalGit/FTP 인증정보 (Credential) 확인&lt;/li&gt;
&lt;li&gt;Local PC/개발PC의 Terminal에서 Git Push (인증정보와 함께)&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Python/Flask는 Azure App Service Container에서 Default Setting 되어 있어서 별다른 할것이 없음 (단순함)&lt;br /&gt;FastAPI 등 기본지원 하지 않는 WSGI는 추가 설정을 해야함&lt;br /&gt;JAVA/Node 등과 같이 Build Process가 포함된 부분은 Build에 관련한 설정이 필요&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;0. [배경] - Azure 웹앱 (App Service)로 Python API 서버 만들기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;AI/ML 연구하는 사람들의 90%는 Jupyter Notebook 에서 전처리/모델을 개발하고 실험 및 과제를 종료 한다고 한다.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이렇게 하면, 자신이 개발한 모델이 우수할 지라도 어느 순간엔가 그냥 사라져 버릴 가능성이 높다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;특히 대기업 같은 경우는, 한해 목표와 KPI를 만족 했다면 그 다음해에는 아무도 신경 쓰지 않는 경우가 많다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일부, 모델이 상용화 적용되는 경우는, Web 개발 파트 혹은 아웃소싱사에서 모델을 Deploy한다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이러한, 이유로 정작 모델을 개발한 사람은 자신이 만든 모델이 활용되는 성취감을 100% 느끼지 못한다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;필자는, 여러가지 내적 동기중에서 작은계단 (Small Step)을 하나씩 걸어올라거면서 성취감/자존감을 하나씩 쌓아 올리는 것이 매우 중요하다고 생각한다. 여러 훌륭한 연구자들 중에 이 부분이 부족하여 자신감이 결여된 인재들을 여럿 보았다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;따라서, 최소의 노력으로 본인들이 개발한 모델/모듈/API를 배포해 보는 것은, 자존감/동기부여/실력향상/업무 등 대부분의 측면에서 긍적적인 효과를 가져온다. 중요한 부분은 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;&quot;최소한의 노력&quot;&lt;/b&gt;&lt;/span&gt;이라는 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다행하게도 요즈음 AWS/Azure/GCP 등 클라우드 환경의 일반화로 서버/네트워크 장비 등 자체구매/운영 (On-Premise) 하지 않아도 되기 때문에, 목표로 하는 최소한의 노력이라는 관점에서 매우 유용한다. 특히, PaaS 서비스 또는 Container를 지원하는 서비스를 사용하여 별다른 신경을 써 주지 않고도 운영/배포 할 수 있다. (단, 처음 학습하는것이 조금 더 시간이 걸릴것 이다. )&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;우선 가장 단순화를 하여 서비스를 Cloud에 올리는 것을 목표로 하여 보자.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;여러 클라우드 서비스가 있겠지만, 필자는 Azure를 사용할 예정이다. AWS가 좀 더 자유도가 높을 것이나, 필자가 보유한 구독이 Azure에 있기 때문에 Azure를 사용하고 있다. (필자 또한 AWS가 더 익숙하긴 하다. ㅜ_ㅜ) Azure 계정/구독이 없는 분은 무료 구독을 사용하면 된다. (약 6개월~1년정도는 사용할 수 있을것이다. )&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Azure에는 App Service라는 웹 어플리케이션 용 PaaS를 제공한다. Java, NodeJS/Javascript, Python, Ruby, PHP 등 대부분의 웹프레임워크를 지원한다. 이 서비스를 이용하면 굳이 WEB/WAS/DB 등 서버를 별도 (VM, On-Prem.)을 생성/구축하지 않고 웹서비스를 구축할 수 있다. 클라우드 환경에서 VM을 활용해서 구축한다면, VM을 생성하고, OS설치/운영하고, OS에 필요 라이브러리를 설치/구동하고, 개발모듈을 올려서 연동하는 등 다수의 구축작업을 해야 한다. 또한 다른 구성요소(Component)간의 연동을 고려한다면 할일이 많아지고, 복잡해지는 만큼 관리요소/운영요소/장애요소 또한 많아지게 된다.&amp;nbsp;Azure App Service, Azure Functions을 활용하면 이러한 부분을 간소화 해서 구축/운영할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;앞서 거론한 바와 같이, 우리는 가장 단순화하여 진행하는 것을 목표로 하고 있으니, 여러 프레임워크중 Python으로 웹프레임워크를 구축/배포해 보도록 하자. &lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Python은 Build 과정이 없이 구동되기 때문에 가장 단순하다. Java, Javascript 등은 Build에 관련된 별도의 yml 파일을 생성해야 된다. 어떤 라이브러리 환경에서, 빌드하고, 배포를 위한 설정들을 지정해 주어야 하므로 다소 복잡해 질 수 있다. 이런 부분은 추후 다루도록 하겠다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음과 같은 순서로 진행하도록 한다.&amp;nbsp;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Python Web Source Code 확보&lt;/li&gt;
&lt;li&gt;Azure App Service 생성&lt;/li&gt;
&lt;li&gt;Source Code 배포 (Azure Upload)&lt;/li&gt;
&lt;li&gt;구동 확인&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참조 : https://learn.microsoft.com/ko-kr/azure/app-service/quickstart-python&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;1. Python Web Source Code&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;본 포스팅에서는, Python Web Source Code는 각자 개발한 내용으로 사용할 수 있으나, 최대한 단순화 하기 위해서 Azure에서 제공하는 Sample을 Github에서 다운로드 받아 사용하도록 한다. 아래는 Python Web Framework인 Flask의 Hello World이다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MS Flask Web App : &lt;a href=&quot;https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;해당 부분 관련하여, 이미 개발코드를 가지고 있다면, 각자 판단에 따라서 진행하면 될것이다. 그러나, 우선 가장 단순한 경우를 테스트하고 응용하는 것이 가장 쉽게 가는 길이라고 생각한다. 나중에 본인의 코드에서 에러가 발생한다면 그 차이점을 인지하여 실수를 고쳐나가기 수월하다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Terminal / CMD 에서 아래와 같이 `git clone &amp;lt;url&amp;gt;`으로 다운로드 받아주자.&lt;/h4&gt;
&lt;pre id=&quot;code_1672990530722&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git clone https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart
$ cd msdocs-python-fastapi-quickstart
$ ll&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEzFL5/btrVuIkiW3g/qEV4WMBIBqdOT5dmsNkZb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEzFL5/btrVuIkiW3g/qEV4WMBIBqdOT5dmsNkZb0/img.png&quot; data-alt=&quot;웹프레임워크 샘플 파일 (MS flask first example )&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEzFL5/btrVuIkiW3g/qEV4WMBIBqdOT5dmsNkZb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEzFL5%2FbtrVuIkiW3g%2FqEV4WMBIBqdOT5dmsNkZb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;556&quot; height=&quot;184&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;웹프레임워크 샘플 파일 (MS flask first example )&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;(소스코드 동작 확인) 로컬에서 정상 동작하는지 일단 확인을 해 보자.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1672991681217&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ python3 -m venv .venv
$ source .venv/bin/activate
$ pip install -r requirements.txt
$ flask run&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;웹브라우저에서 접속해서 확인해 보자 : `http://localhost:5000/`&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Flask 외에 다른 Web Framework를 사용하다면, 기본 Port가 달라질 수 있다. 예를 들어, Django, FastAPI는 기본 Port로 8000을 사용한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWy6g9/btrVvtUKPWt/8NjKlehk15mqaRixUmt4gK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWy6g9/btrVvtUKPWt/8NjKlehk15mqaRixUmt4gK/img.png&quot; data-alt=&quot;Azure flask web sample 구동 화면 (Local 구동)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWy6g9/btrVvtUKPWt/8NjKlehk15mqaRixUmt4gK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWy6g9%2FbtrVvtUKPWt%2F8NjKlehk15mqaRixUmt4gK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;344&quot; height=&quot;345&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Azure flask web sample 구동 화면 (Local 구동)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;2. Azure App Service 생성/설정&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음으로 Azure에 App Service를 생성해 준다. App Service를 생성하는 방법은, 1) Azure Portal, 2) Azure CLI, 3) VS Code, 4) Azure SDK 등 다양하다. 다만, 각 행위자체를 GUI로 하느냐, 명령어로 하느냐, IDE로 하느냐 등만 차이가 있을 뿐이다. 본 포스팅에서는 가장 일반적인 Azure Portal (GUI)를 사용해서 진행하도록 하자.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Azure Portal에 접속 (https://portal.azure.com)하여 로그인을하고, 좌측 상단 메뉴에서 &quot;리소스 만들기&quot; 누른다. 또는 상단에 추천메뉴에 리소스 만들기가 위치해 있다. (찾기 쉬울것이다.)&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvUIy1/btrVzvc4CcH/EbAZojAHColRmXZAkw7fWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvUIy1/btrVzvc4CcH/EbAZojAHColRmXZAkw7fWk/img.png&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;235&quot; data-is-animation=&quot;false&quot; style=&quot;width: 84.1668%; margin-right: 10px;&quot; data-widthpercent=&quot;85.16&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvUIy1/btrVzvc4CcH/EbAZojAHColRmXZAkw7fWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvUIy1%2FbtrVzvc4CcH%2FEbAZojAHColRmXZAkw7fWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;867&quot; height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHhd2a/btrVzFGt7lc/lstGIEkodhZ3HDkQxKic5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHhd2a/btrVzFGt7lc/lstGIEkodhZ3HDkQxKic5K/img.png&quot; data-origin-width=&quot;227&quot; data-origin-height=&quot;353&quot; data-is-animation=&quot;false&quot; style=&quot;width: 14.6704%;&quot; data-widthpercent=&quot;14.84&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHhd2a/btrVzFGt7lc/lstGIEkodhZ3HDkQxKic5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHhd2a%2FbtrVzFGt7lc%2FlstGIEkodhZ3HDkQxKic5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;227&quot; height=&quot;353&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Azure Portal 리소스 만들기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리소스 만들기를 실행하여, 여러가지 Azure의 지원 기능이 나온다. 그중에서 웹앱을 선택하자. 만약 여기까지 경로를 찾지 못했다면, 상단 리소스 메뉴에서 &quot;웹앱&quot; 또는 &quot;App Service&quot;를 입력하면 된다.&amp;nbsp; 이제 실제 &quot;웹앱 만들기&quot; 페이지로 들어와 중요 정보를 몇가지 입력해야 한다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DyQqs/btrVzGFrkYg/OFCvlKoMKYwd9r8Jl8OVBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DyQqs/btrVzGFrkYg/OFCvlKoMKYwd9r8Jl8OVBk/img.png&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;637&quot; data-is-animation=&quot;false&quot; style=&quot;width: 52.5889%; margin-right: 10px;&quot; data-widthpercent=&quot;53.21&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DyQqs/btrVzGFrkYg/OFCvlKoMKYwd9r8Jl8OVBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDyQqs%2FbtrVzGFrkYg%2FOFCvlKoMKYwd9r8Jl8OVBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;770&quot; height=&quot;637&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQqBNs/btrVvkwVw8F/LXkBpfOESAJy0cEUZQ3D0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQqBNs/btrVvkwVw8F/LXkBpfOESAJy0cEUZQ3D0K/img.png&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;682&quot; data-is-animation=&quot;false&quot; style=&quot;width: 46.2483%;&quot; data-widthpercent=&quot;46.79&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQqBNs/btrVvkwVw8F/LXkBpfOESAJy0cEUZQ3D0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQqBNs%2FbtrVvkwVw8F%2FLXkBpfOESAJy0cEUZQ3D0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;725&quot; height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Azure 웹앱 (App Service) 생성 (좌), 웹앱 만들기 및 설정 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;웹앱 만들기 페이지에서 가장 중요한 설정 부분은 다음과 같다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구독/리소스그룹 : 본인의 구독과 리소스 그룹을 선택 or 생성해 주면 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;웹앱 이름 : &lt;span style=&quot;background-color: #f3c000;&quot;&gt;겹치지 않도록 이름을 설정하자.&lt;/span&gt; 예) &quot;azure-webapp-python-test&quot;&lt;br /&gt;이 이름은 웹앱 생성후, &quot;https://&amp;lt;웹앱이름&amp;gt;.azurewebsites.net&quot;로 azure 기본 제공하는 subdomain name이 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;게시 방식 : 코드, docker 컨테이너, 정적웹앱. &lt;span style=&quot;background-color: #f3c000;&quot;&gt;우리는 가장 단순하게 &quot;코드&quot;를 선택하도록 하자.&lt;/span&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;런타임 스택 : &lt;span style=&quot;background-color: #f3c000;&quot;&gt;Python 3.9를 선택.&lt;/span&gt; 다른버전 선택도 가능하다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;운영체제 : Linux. (Windows를 선택해도 무방하나, 본 포스팅은 Linux를 기반으로 진행한다.)&lt;/li&gt;
&lt;li&gt;지역 : 본인이 편한 위치를 선택하면 된다. Azure는 Korea Central Region이 있으므로, 이것을 선택하는 것을 추천한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;가격정책플랜 : 우리는 테스트 해보는 것이기 때문에 기본으로 사용하자.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&quot;검토 + 만들기 &quot;&lt;/span&gt; 버튼을 누른다. 유효성이 검토되면 설정에 대한 요약페이지가 출력되고, &lt;span style=&quot;background-color: #f3c000;&quot;&gt;최종적으로 하단에 &quot;만들기&quot; 버튼&lt;/span&gt;을 또 한번 눌러 주어야 한다. 이후. &quot;...배포 진행 중&quot;이라는 페이지가 출력 될 것이다. 2~3분 기다리면 &quot;배포 성공&quot; 메세지가 출력된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&quot;리소스 이동&quot; 버튼을 눌러준다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;배포 탭으로 가면, Github Actions를 설정하는 메뉴가 나온다. 그러나, 현 시점에서 Github Actions은 사용하지 않을 예정이다. 우리는 단순하게 Local Git을 사용하도록 하자. 이후에 Build가 필요한 NodeJS or JAVA 등을 사용할 때는 Github Actions이 매우 유용하다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nXKzA/btrVv3Pjx6t/MlF84GgWWvTPgXxKZZGYd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nXKzA/btrVv3Pjx6t/MlF84GgWWvTPgXxKZZGYd0/img.png&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;374&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;46.36&quot; style=&quot;width: 45.8217%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nXKzA/btrVv3Pjx6t/MlF84GgWWvTPgXxKZZGYd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnXKzA%2FbtrVv3Pjx6t%2FMlF84GgWWvTPgXxKZZGYd0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;487&quot; height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3gfSX/btrVzVh86ZX/lzyL4UvpW0N841K6zHvti1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3gfSX/btrVzVh86ZX/lzyL4UvpW0N841K6zHvti1/img.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;685&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.0155%;&quot; data-widthpercent=&quot;53.64&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3gfSX/btrVzVh86ZX/lzyL4UvpW0N841K6zHvti1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3gfSX%2FbtrVzVh86ZX%2FlzyL4UvpW0N841K6zHvti1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1032&quot; height=&quot;685&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;웹앱 생성완료 후 리소스 이동 (좌), 웹앱 개요 및 배포센터 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이제 Azure 웹앱 (App Service)가 생성이 완료되었다. &quot;리소스로 이동&quot;하여 웹앱의 왼쪽 메뉴중 &quot;개요&quot;를 보면, 전반적인 웹앱의 정보가 출력된다. 여기에서 중요한 것은 우측 상단에 있는 URL, FTP/FTPS 등의 정보가 매우 중요하다. FTP를 통하여 배포할 때 사용할 수 있다. (민감정보이므로 타인에게 노출되지 않도록 한다.)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이제 우선 해야할 일을, 웹앱에 코드를 배포하는 일 이므로, 좌측에 &quot;배포 센터&quot;로 이동한다. (영어식 표기, Deployment Center)&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;본 포스팅에서는 FTP로 배포하지는 않도록한다. 이유인 즉, FTP 배포는 실제 잘 사용하지 않을 뿐만 아니라 오류/실수 발생할 때의 대책이 없기 때문에, 정말 테스트할 때 이외는 가급적 사용하지 않도록 하자. 대부분은 Git을 사용할 것이다. ML 엔지니어 입장에서 Git을 사용하는 웹(Front/Backend)개발자들과 협업하기 위해서도 기술스택을 맞추어 두는 것이 바람직 하다.&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;배포센터 버튼을 누르면, 페이지가 출력될때가지 다소 시간이 걸릴 수도 있다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;우리는 앞서 웹앱을 생성할 때, 설정 단계를 Skip하였기 때문에 배포센터에서 더욱 상세한 설정을 한다. 가장 중요한 대분류는 소스를 어떤 방법으로 배포할 것인가에 대한 결정이다. 실제 상용에서는 Stage-&amp;gt;Production으로 나누어서 지속배포(CI/CD)체계를 구축할 것이나, 본 포스팅은 단순화하여, &quot;로컬 Git&quot;을 사용하여 배포하는 것으로 진행한다. &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&quot;소스 &amp;gt; 로컬 Git&quot;을 선택해 주자.&amp;nbsp; (배포 하는중...)이라는 메세지가 출력된다. (잠시 기다리자)&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KEqNq/btrVyWa5PQr/7UbiSd07ITS48ln8Bu3Vlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KEqNq/btrVyWa5PQr/7UbiSd07ITS48ln8Bu3Vlk/img.png&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;398&quot; data-is-animation=&quot;false&quot; style=&quot;width: 33.7678%; margin-right: 10px;&quot; data-widthpercent=&quot;34.57&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KEqNq/btrVyWa5PQr/7UbiSd07ITS48ln8Bu3Vlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKEqNq%2FbtrVyWa5PQr%2F7UbiSd07ITS48ln8Bu3Vlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;470&quot; height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/syZfH/btrVzzmknJS/YsVzj7JuiThzurT8Kksk20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/syZfH/btrVzzmknJS/YsVzj7JuiThzurT8Kksk20/img.png&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;552&quot; data-is-animation=&quot;false&quot; style=&quot;width: 29.7345%; margin-right: 10px;&quot; data-widthpercent=&quot;30.44&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/syZfH/btrVzzmknJS/YsVzj7JuiThzurT8Kksk20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsyZfH%2FbtrVzzmknJS%2FYsVzj7JuiThzurT8Kksk20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;574&quot; height=&quot;552&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TDDlo/btrVA1B6FGO/QN5XlATgJMuoY8NbnIS4H0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TDDlo/btrVA1B6FGO/QN5XlATgJMuoY8NbnIS4H0/img.png&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;605&quot; data-is-animation=&quot;false&quot; style=&quot;width: 34.1721%;&quot; data-widthpercent=&quot;34.99&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TDDlo/btrVA1B6FGO/QN5XlATgJMuoY8NbnIS4H0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTDDlo%2FbtrVA1B6FGO%2FQN5XlATgJMuoY8NbnIS4H0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;723&quot; height=&quot;605&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;웹앱 (app service)의 소스 배포방식 : 로컬 Git 선택 (좌), 저장 실행(중), FTP 자격증명의 인증정보 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;저장 버튼을 누르지 않으면 아무런 일도 발생하지 않는다. 설정 저장을 하면, 웹앱 서비스 (Container)가 재시작 된다. 컨테이너가 처음부터 시작되기 때문에 반영되는데 1~2분 정도 소요가 될수 있다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설정 저장이 완료 되면, 해당 페이지에 &quot;Git Clone URI&quot; 정보가 출력된다. 이 URI로 우리는 `git push`를 실행하게 되니, URI을 복사해 두자.&amp;nbsp; 또한, git push를 할 때 인증정보는 &quot;FTP 자격증명&quot; 메뉴에서 확인 할 수 있다. 해당 탭에서 GIT Clone URI를 다시 확인할 수 있으며, 사용자 이름/암호를 확인할 수 있다. (당연하겠지만 취급에 주의가 필요하다.) 향후에는 &quot;게시 프로필 관리&quot;를 통해서 인증이 관리되어야 할것이다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Local Git 설정이 완료되면, &quot;FTP 자격증명&quot; 메뉴의 명칭은 &quot;로컬 Git/FTPS 자격 증명&quot;으로 변경된다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;여기에서 중요한점 중 하나는, 사용자 이름이다. 필자의 경우, 이 때문에 인증에 어려움을 겪었다. 사용자 이름은 기본적으로 다음과 같이 표기되어 있다.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1672995779910&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;웹앱 이름&amp;gt;\$&amp;lt;웹앱 이름&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 Git Push 할 때 인증은 &quot;$&amp;lt;웹앱 이름&amp;gt;&quot; 부분만 사용된다. 예를 들어 표기된 사용자 이름이 &quot;flask-test\$flask-test&quot;라면, 실제 사용되는 부분은 $를 포함한 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&quot;$flask-test&quot;&lt;/span&gt; 부분이 해당된다. 이부분을 잘못 입력하면 인증실패로 git push가 실행되지 않는다. 패스워드의 경우 전체를 복사하여 사용하면 된다.&amp;nbsp; 다음은 공식 가이드에서 제공하는 이미지 이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1141&quot; data-origin-height=&quot;539&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lWSJH/btrVzx9UBB5/3vEKhgWu0vG0iDM7N30Q0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lWSJH/btrVzx9UBB5/3vEKhgWu0vG0iDM7N30Q0k/img.png&quot; data-alt=&quot;Local Git에서 사용자 이름 영역을 조심해야 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lWSJH/btrVzx9UBB5/3vEKhgWu0vG0iDM7N30Q0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlWSJH%2FbtrVzx9UBB5%2F3vEKhgWu0vG0iDM7N30Q0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1141&quot; height=&quot;539&quot; data-origin-width=&quot;1141&quot; data-origin-height=&quot;539&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Local Git에서 사용자 이름 영역을 조심해야 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;이제 Azure Portal에서 설정할 내용은 완료하였다. 다음은 Terminal 에서 Git push를 진행하면된다.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;본 포스팅에서는 별도 빌드 또는 추가 설정이 필요없기 때문에 &quot;설정/구성&quot;을 추가로 진행하지 않았다. 그러나, 상세설정 들이 필요하다면 아래처럼 &quot;구성&quot; 메뉴에서 &quot;application 설정&quot;, &quot;시작 명령어&quot; 등을 상세 지정할 수 있다.&amp;nbsp;&quot;구성&amp;gt;애플리케이션 설정&quot;은 Application 내부에서 사용할 별도의 설정을 지정할 수 있는데, 우리는 여기는 넘어가도록 하자.&amp;nbsp; FAST API 배포는 Flask 보다는 조금 더 복잡한데, 이 때 다시 한번 거론 하도록 하겠다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqYLeW/btrVxrPTQOc/YhLdcZ8fj7eE54In6MwfB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqYLeW/btrVxrPTQOc/YhLdcZ8fj7eE54In6MwfB0/img.png&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;627&quot; data-is-animation=&quot;false&quot; style=&quot;width: 59.9854%; margin-right: 10px;&quot; data-widthpercent=&quot;60.69&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqYLeW/btrVxrPTQOc/YhLdcZ8fj7eE54In6MwfB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqYLeW%2FbtrVxrPTQOc%2FYhLdcZ8fj7eE54In6MwfB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;520&quot; height=&quot;627&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFu4k0/btrVAtMmZJC/KoQyRv8W7mdKR9qqltBONk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFu4k0/btrVAtMmZJC/KoQyRv8W7mdKR9qqltBONk/img.png&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;767&quot; data-is-animation=&quot;false&quot; style=&quot;width: 38.8518%;&quot; data-widthpercent=&quot;39.31&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFu4k0/btrVAtMmZJC/KoQyRv8W7mdKR9qqltBONk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFu4k0%2FbtrVAtMmZJC%2FKoQyRv8W7mdKR9qqltBONk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;412&quot; height=&quot;767&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;추가 설정이 필요한 &quot;애플리케이션 설정&quot;, 일반설정 및 시작 명령 설정하는 화면의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;3. Local Git - 소스코드 배포&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;앞에서 우리는 git clone을 통하여 Azure Flask Sample 코드를 다운로드 받았다. 해당 폴더로 이동하여 Git Push를 진행하도록 하자. 이 때 &amp;lt;GIT URI&amp;gt;는 Azure Portal의 &quot;Local Git 자격증명&quot;에서 확인한 Git Clone URI이다. 사용자명/패스워드는 이전 절에서 거론했던 내용을 사용하자.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;다음 명령어를 실행하여 Azure에 소스코드를 배포하도록 하자.&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1672997168173&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git remote add azure &amp;lt;GIT URI&amp;gt;
$ git push -u azure main:master&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;변경 사항이 있다면, `git add` 와 `git commit` 을 통하여 리파지토리에 반영하도록 하자.&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Azure 웹앱에서 기본 구동하는 브랜치는 master이다. 이 때문에, 최근에 사용하는 기본 브랜치명 'main'과 다를 수 있는데, 이들을 매핑해 주기 위해, `git push -u azure main` 대신 `git push -u azure main:master`를 사용하였다.&amp;nbsp; 만약 사용하는 브랜치가 &quot;master&quot;로 되어 있다면, `git push -u azure master`를 사용하면 되겠다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이제 소스코드 배포를 완료 했다. 앞서 거론했든이 Python은 별다른 빌드를 하지 않기 때문에, 별다른 설정파일 없이 웹앱을 생성할 수 있다. 이제 웹앱의 &quot;개요&quot;페이지에서 확인할 수 있는 웹앱 URL을 확인하고, 웹브라우저로 접속해 보기 바란다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;아래와 같이 웹브라우저에서 정상 동작하는 것을 확인할 수 있다. 해당 예제에서는 Python/Jinja2템플릿을 사용하여 웹페이지 (Frontent)를 구성했으나, API서버를 구축/배포하기 위해서 굳이 웹페이지가 필요하지 않을 수 있다. Flask/FastAPI/Django 등의 프레임워크에서 해당 Rest Api를 잘 정의하여 사용하면 된다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cigWQp/btrVzzzY6Ma/TOKKlA5HLxZRU0g9EClaGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cigWQp/btrVzzzY6Ma/TOKKlA5HLxZRU0g9EClaGK/img.png&quot; data-origin-width=&quot;396&quot; data-origin-height=&quot;468&quot; data-is-animation=&quot;false&quot; style=&quot;width: 20.604%; margin-right: 10px;&quot; data-widthpercent=&quot;21.09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cigWQp/btrVzzzY6Ma/TOKKlA5HLxZRU0g9EClaGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcigWQp%2FbtrVzzzY6Ma%2FTOKKlA5HLxZRU0g9EClaGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;396&quot; height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN9ocD/btrVzmVdx6J/hm6dbFknWOHcOZpKuZ7dRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN9ocD/btrVzmVdx6J/hm6dbFknWOHcOZpKuZ7dRk/img.png&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;222&quot; data-is-animation=&quot;false&quot; style=&quot;width: 36.6349%; margin-right: 10px;&quot; data-widthpercent=&quot;37.51&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN9ocD/btrVzmVdx6J/hm6dbFknWOHcOZpKuZ7dRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN9ocD%2FbtrVzmVdx6J%2Fhm6dbFknWOHcOZpKuZ7dRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;334&quot; height=&quot;222&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CPmyf/btrVxrvOmzr/HN2rvBJKoucZloYTOQy9K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CPmyf/btrVxrvOmzr/HN2rvBJKoucZloYTOQy9K0/img.png&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;548&quot; data-is-animation=&quot;false&quot; style=&quot;width: 40.4355%;&quot; data-widthpercent=&quot;41.4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CPmyf/btrVxrvOmzr/HN2rvBJKoucZloYTOQy9K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCPmyf%2FbtrVxrvOmzr%2FHN2rvBJKoucZloYTOQy9K0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;910&quot; height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Azure 배포 완료된 예 (좌), RestAPI 리스트 (중), API 구현 코드 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;기타.&amp;nbsp; Azure 웹앱의 기본 동작&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Azure 웹앱 (App Service)는 기본적으로 Docker Container로 구동한다. 동작하는 구조를 살펴보면, 막무가내식 프로세스를 외우는것보다 더 효율적 일 수 있다. 필자의 경우, Azure 웹앱 앞부분에 NginX가 구동되고 있는 것을 알지 못했다. 이 때문에, 기본적으로 제공하는 웹프레임워크 외 FastAPI 등을 배포(Deploy)할 때 애를 많이 먹었다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;내부적으로 Azure 웹앱 (App Service)은 Oryx 라는 Container 빌드 패키지를 사용한다. oryx의 상세 파라미터는 아래를 참조 바란다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/Oryx/blob/main/doc/configuration.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/microsoft/Oryx/blob/main/doc/configuration.md&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;우선 Azure 웹앱이 Python 환경에서 사용하는 Docker Container구성을 살펴보면, 다음과 같은 Component로 이루어져 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1673061504431&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Browser &amp;lt;-&amp;gt; nginx &amp;lt;-&amp;gt; /tmp/uwsgi.sock &amp;lt;-&amp;gt; uWSGI &amp;lt;-&amp;gt; Your Python app &amp;lt;-&amp;gt; Psycopg2 &amp;lt;-&amp;gt; remote PostgreSQL database&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;참조: &lt;a href=&quot;https://github.com/Azure-App-Service/python&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Azure-App-Service/python&lt;/a&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Client의 브라우저에서 우리의 앱(App)까지 도달하기 위해서 그 사이에 Nginx와, uWSGI를 거쳐야하는 구조이다. 즉, nginx 등 설정에 따라서, 우리의 APP가 영향 받을 수 있다는 것이다.&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 점을 인지하고 있어야 한다.&lt;br /&gt;그러나, nginx가 동작하는 부분은 ssh서 내부를 살펴봐도 없다.&amp;nbsp;&lt;br /&gt;아마도, 웹앱(App Service)지원하는 host/hypervisor에서 동작하는 듯 하다.&amp;nbsp;&lt;br /&gt;다만, user가 확인할 수 있는 부분은 `netstat -an`을 실행하면, unix소켓으로 app쪽으로 포워딩 해주는 것을 확인할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;또한, 해당 Docker Container에 기본으로 설치된 웹프레임워크는 Flask와 Django이다. 이 두 프레임워크 외의 다른 웹프레임워크는 커스텀 설정을 해야 한다는 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Azure 웹앱에서 사용하는 Python Container의 Dockerfile을 살펴 보면 다음과 같다. 이 Dockerfile을 살펴보면, 내부에서 어떤 동작을 하는지 상세하게 이해 할 수 있을 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Dockerfile]&lt;/p&gt;
&lt;pre id=&quot;code_1673062081858&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FROM mcr.microsoft.com/oryx/python:3.7-20190712.5
LABEL maintainer=&quot;appsvc-images@microsoft.com&quot;

# Web Site Home
ENV HOME_SITE &quot;/home/site/wwwroot&quot;

#Install system dependencies
RUN apt-get update \
    &amp;amp;&amp;amp; apt-get install -y --no-install-recommends \
        openssh-server \
        vim \
        curl \
        wget \
        tcptraceroute \
    &amp;amp;&amp;amp; pip install --upgrade pip \
    &amp;amp;&amp;amp; pip install subprocess32 \
    &amp;amp;&amp;amp; pip install gunicorn \ 
    &amp;amp;&amp;amp; pip install virtualenv \
    &amp;amp;&amp;amp; pip install flask 

WORKDIR ${HOME_SITE}

EXPOSE 8000
ENV PORT 8000
ENV SSH_PORT 2222

# setup SSH
RUN mkdir -p /home/LogFiles \
     &amp;amp;&amp;amp; echo &quot;root:Docker!&quot; | chpasswd \
     &amp;amp;&amp;amp; echo &quot;cd /home&quot; &amp;gt;&amp;gt; /etc/bash.bashrc 

COPY sshd_config /etc/ssh/
RUN mkdir -p /opt/startup
COPY init_container.sh /opt/startup/init_container.sh

# setup default site
RUN mkdir /opt/defaultsite
COPY hostingstart.html /opt/defaultsite
COPY application.py /opt/defaultsite

# configure startup
RUN chmod -R 777 /opt/startup
COPY entrypoint.py /usr/local/bin

ENTRYPOINT [&quot;/opt/startup/init_container.sh&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그렇다면, Dockerfile에 따라 Container를 실행하고 초기화하는 startup.sh을 확인해 보자.&amp;nbsp; 웹앱은 지정된 프레임워크를 탑재한 Container를 하나 띄우고, 시작 설정을 실행한다. 이 부분이 Azure Portal에서 선택한 프레임워크에 따라서 결정된다. 이후 Container 시작 후에 &quot;run&quot;해주는 startup.sh을 실행 시켜 준다. (python의 경우) startup.sh의 내용을 잠깐 살펴 보면 아래와 같다. 들여다 보면,&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[startup.sh]&lt;/p&gt;
&lt;pre id=&quot;code_1672998705251&quot; class=&quot;routeros&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /tmp/8dxxxxxxxxxxxxxa6

export APP_PATH=&quot;/tmp/8dxxxxxxxxxxxxxa6&quot;
if [ -z &quot;$HOST&quot; ]; then
                export HOST=0.0.0.0
fi
if [ -z &quot;$PORT&quot; ]; then
                export PORT=80
fi

export PATH=&quot;/opt/python/3.9.15/bin:${PATH}&quot;
echo 'export VIRTUALENVIRONMENT_PATH=&quot;/tmp/8dxxxxxxxxxxxxxa6/antenv&quot;' &amp;gt;&amp;gt; ~/.bashrc
echo '. antenv/bin/activate' &amp;gt;&amp;gt; ~/.bashrc
PYTHON_VERSION=$(python -c &quot;import sys; print(str(sys.version_info.major) + '.' + str(sys.version_info.minor))&quot;)
echo Using packages from virtual environment 'antenv' located at '/tmp/8daed8eb14755a6/antenv'.
export PYTHONPATH=$PYTHONPATH:&quot;/tmp/8dxxxxxxxxxxxxxa6/antenv/lib/python$PYTHON_VERSION/site-packages&quot;
echo &quot;Updated PYTHONPATH to '$PYTHONPATH'&quot;
. antenv/bin/activate
GUNICORN_CMD_ARGS=&quot;--timeout 600 --access-logfile '-' --error-logfile '-' -c /opt/startup/gunicorn.conf.py --chdir=/tmp/8dxxxxxxxxxxxxxa6&quot; gunicorn app:app&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;기타.&amp;nbsp; Azure 웹앱 디버깅&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;추가적으로 웹앱에서는 Container 내부로 직접 접근하는 수단을 몇가지 제공한다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;환경변수&lt;/li&gt;
&lt;li&gt;SSH&lt;/li&gt;
&lt;li&gt;Bash&lt;/li&gt;
&lt;li&gt;Log&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k6BMh/btrVAtseewe/w1SdzUokmAtOGqvXE7yX81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k6BMh/btrVAtseewe/w1SdzUokmAtOGqvXE7yX81/img.png&quot; data-origin-width=&quot;248&quot; data-origin-height=&quot;574&quot; data-is-animation=&quot;false&quot; style=&quot;width: 25.8418%; margin-right: 10px;&quot; data-widthpercent=&quot;26.15&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k6BMh/btrVAtseewe/w1SdzUokmAtOGqvXE7yX81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk6BMh%2FbtrVAtseewe%2Fw1SdzUokmAtOGqvXE7yX81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;248&quot; height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxJ74i/btrVBRNiWay/NhM41m6JVHmOKEPKPsJcuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxJ74i/btrVBRNiWay/NhM41m6JVHmOKEPKPsJcuk/img.png&quot; data-origin-width=&quot;681&quot; data-origin-height=&quot;558&quot; data-is-animation=&quot;false&quot; style=&quot;width: 72.9954%;&quot; data-widthpercent=&quot;73.85&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxJ74i/btrVBRNiWay/NhM41m6JVHmOKEPKPsJcuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxJ74i%2FbtrVBRNiWay%2FNhM41m6JVHmOKEPKPsJcuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;681&quot; height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Container/Sandbox에 직접 접근할 수 있는 수단 (SSH, BASH)을 제공하고, Log 등을 확인 할 수 있다.&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중에서 가장 유용한 SSH 접속은 다음 URL로 바로 접근 할 수 있으니, 유용하게 사용하기 바란다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tdiag-ml-api.scm.azurewebsites.net/webssh/host&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://&amp;lt;앱이름&amp;gt;.scm.azurewebsites.net/webssh/host&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>app service</category>
      <category>Azure</category>
      <category>Azure App Deploy Process</category>
      <category>Azure Flask</category>
      <category>Azure Local Git</category>
      <category>Azure Web Deploy</category>
      <category>Azure Web Service</category>
      <category>flask api</category>
      <category>애저 웹앱 배포</category>
      <category>웹앱</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/213</guid>
      <comments>https://windflex.tistory.com/213#entry213comment</comments>
      <pubDate>Sat, 7 Jan 2023 13:55:12 +0900</pubDate>
    </item>
    <item>
      <title>[Conda-Jupyter] Conda 가상환경과 Jupyter Kernel 연동/생성/삭제</title>
      <link>https://windflex.tistory.com/212</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Jupyter Kernel 추가] conda 가상환경을 jupyter Kernel로 추가하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/207&quot;&gt;2022.09.19 - [개발 이야기/Python] - [주피터노트북 커널] jupyter lab/notebook kernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/126&quot;&gt;2020.06.04 - [개발 이야기/Python] - [파이썬] Anaconda x Jupyter notebook 설치 및 설정 방법 - 가상환경으로 파이썬 개발환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/19&quot;&gt;2020.03.10 - [IT 이야기] - Python x Jupyter Notebook 설치 및 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/206&quot;&gt;2022.09.19 - [IT 이야기/IT 상식] - [Python 가상환경] conda 설치 및 가상환경 (feat. 내부 로직 &amp;amp; cheat sheet)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1112&quot; data-origin-height=&quot;989&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QQHmU/btrSWaX3baI/OviHf0gLWH2M4Xa5Cu8zu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QQHmU/btrSWaX3baI/OviHf0gLWH2M4Xa5Cu8zu1/img.png&quot; data-alt=&quot;python / Conda 가상환경과 Jupyter Kernel의 관계는 어떻게 될까? 왜 Kernel을 새롭게 만들어도 설치된 패키지가 다르게 인식될까?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QQHmU/btrSWaX3baI/OviHf0gLWH2M4Xa5Cu8zu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQQHmU%2FbtrSWaX3baI%2FOviHf0gLWH2M4Xa5Cu8zu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;675&quot; height=&quot;600&quot; data-origin-width=&quot;1112&quot; data-origin-height=&quot;989&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;python / Conda 가상환경과 Jupyter Kernel의 관계는 어떻게 될까? 왜 Kernel을 새롭게 만들어도 설치된 패키지가 다르게 인식될까?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[요약]&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;conda 명령어
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;가상환경 생성 :&lt;/b&gt;&lt;/span&gt; `conda create -n &amp;lt;가상환경 이름&amp;gt; python=&amp;lt;python버전&amp;gt;`. ex) conda create -n env_test python=3.9&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;가상환경 삭제 :&lt;/b&gt;&lt;/span&gt; `conda env remove --name &amp;lt;가상환경 이름&amp;gt;` ex) conda remove -n env_test&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;가상환경 활성화/비활성화 :&lt;/b&gt; &lt;/span&gt;`conda activate &amp;lt;가상환경 이름&amp;gt;` / `conda deactivate`&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;가상환경 목록 :&lt;/b&gt;&lt;/span&gt; `conda env list` or `conda info --envs`&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;-n 옵션은 `--name` 옵션과 동일합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;jupyter kernel 명령어
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;현상 / 원인파악 :&lt;/b&gt; &lt;/span&gt;기본환경에서 jupyter notebook/ jupyterlab kernel과 conda 가상환경은 연동되지 않음.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;Jupyter 커널 목록 확인 :&lt;/b&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;`jupyter kernelspec list`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;conda-Jupyter 연동 패키지 설치 :&amp;nbsp;&lt;/b&gt;&lt;/span&gt; &lt;span style=&quot;background-color: #f89009;&quot;&gt;`conda install nb_conda_kernels`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;연동 : 1) 가상환경 활성화 , 2) Jupyter 커널 생성, 3) 결과 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1) 가상환경 활성화 : &lt;span style=&quot;background-color: #f89009;&quot;&gt;conda activate &amp;lt;가상환경 이름&amp;gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;2) 커널 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;`pip install ipykernel`&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;`ipython kernel install --user --name=&amp;lt;가상환경 이름&amp;gt;`&lt;/span&gt; &lt;br /&gt;혹은 &lt;span style=&quot;background-color: #f89009;&quot;&gt;`python -m ipykernel install --user --name=&amp;lt;가상환경 이름&amp;gt;`&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;3) 결과 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;pip list 또는 import &amp;lt;library&amp;gt; 확인&lt;/li&gt;
&lt;li&gt;kernel.json 확인 ( kernel.json은 해당 kernel의 경로에 위치함. 해당 kernel경로는&lt;span style=&quot;background-color: #f89009;&quot;&gt; `jupyter kernelspec list`&lt;/span&gt; 명령으로 확인)&lt;/li&gt;
&lt;li&gt;결과적으로 Jupyter kernel에 대한 설정은, `nb_conda_kernels`은 kernel.json 내용을 conda env list 내용에 맞게 수정하는 것임&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;jupyter 커널 삭제 :&lt;/span&gt; &lt;/b&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;`jupyter kernelspec uninstall env_test` &lt;/span&gt;또는 &lt;span style=&quot;background-color: #f89009;&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;`jupyter kernelspec remove env_test`&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;ipykernel이 없는 경우, `pip install ipykernel` 실행&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;jupyter의 kernel생성 할 때 기본 설정(nb_conda_kernel이 없는 경우)은&amp;nbsp; &quot;os 기본 python 환경에서 실행됨&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Conda 가상환경 vs. Jupyter Kernel&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;conda를 이용해서 가상환경 생성 (아래 명령줄)을 생성해 보자. 그리고, 필요한 라이브러리를 설치해 보자. 아래는 예제로 torch를 설치한다.&lt;/h4&gt;
&lt;pre id=&quot;code_1670315102601&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda create -n env_test python=3.9

$ conda activate env_test
$ pip install torch
$ conda deactivate&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Jupyter Kernel 확인을 위해서 아래와 같이 `jupyter kernelspec list` 를 실행해 보면, 당연하게도 conda에서 추가한 가상환경은 kernel에 등록되어 있지 않다. conda package manager와 Jupyter는 아무런 연관이 없다. (연동같은거 안 해준다.)&amp;nbsp; Google 검색으로 &quot;Jupyter Kernel 추가하기&quot;라고 찾아보자. 아래와 같이 ipykernel을 통해서 커널을 추가하는 내용 결과를 얻을 수 있다. 그러나, 이 명령어는 conda 및 가상환경과는 무관하게 말 그대로 Jupyter Kernel을 생성해 준다. 기본값을 사용하여 환경을 살펴보면, 생성된 Kernel로 실행되는 Python 환경은 OS 기본 Python이거나 (base) 가상환경 이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;빈번하게 발생하는 실수 중 하나는 conda를 통해서 생성한 가상환경과, Jupyter kernel의 이름이 동일하다고 하여 동일한 가상환경으로 착각하는 것이다. 기본적으로, 이 둘은 단지 표기되는 문자열만 동일할 뿐이다. 이번 포스팅에서는 conda 가상환경 설정과, Jupyter kernel을 살펴보고,&amp;nbsp; Conda &lt;b&gt;가상환경과 Jupyter의 커널을 동기화&lt;/b&gt;하는 것이다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Jupyter의 Kernel로 코드를 작성....&lt;br /&gt;....&lt;br /&gt;....이 아니라&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;u&gt;&lt;b&gt;에러가 난다.&lt;/b&gt;&lt;/u&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X0ebV/btrSWaQZQJj/gYkxjlnl1m3PPUtEi1yFq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X0ebV/btrSWaQZQJj/gYkxjlnl1m3PPUtEi1yFq1/img.png&quot; style=&quot;width: 27.8834%; margin-right: 10px;&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;183&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;28.21&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X0ebV/btrSWaQZQJj/gYkxjlnl1m3PPUtEi1yFq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX0ebV%2FbtrSWaQZQJj%2FgYkxjlnl1m3PPUtEi1yFq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;297&quot; height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VZ0On/btrS09WOyGr/gHjG0A44GHhh1oWI9eKOfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VZ0On/btrS09WOyGr/gHjG0A44GHhh1oWI9eKOfK/img.png&quot; style=&quot;width: 70.9539%;&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;154&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;71.79&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VZ0On/btrS09WOyGr/gHjG0A44GHhh1oWI9eKOfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVZ0On%2FbtrS09WOyGr%2FgHjG0A44GHhh1oWI9eKOfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;636&quot; height=&quot;154&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Jupyter Web UI에서 새로 생성한 Kernel을 선택할 수 있다(좌), 그러나 앞서 설치한 라이브러리는 import 되지 않은다.(우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1670330005685&quot; class=&quot;applescript&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda activate env_test
$ pip list&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kwyL2/btrSW5PsEdB/PxBOhxjgj3HdtSOpOlK6X0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kwyL2/btrSW5PsEdB/PxBOhxjgj3HdtSOpOlK6X0/img.png&quot; style=&quot;width: 60.599%; margin-right: 10px;&quot; data-origin-width=&quot;321&quot; data-origin-height=&quot;190&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;61.31&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kwyL2/btrSW5PsEdB/PxBOhxjgj3HdtSOpOlK6X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkwyL2%2FbtrSW5PsEdB%2FPxBOhxjgj3HdtSOpOlK6X0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;321&quot; height=&quot;190&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d88fuT/btrSZR3WPR9/ukhiF1qAm18GIHHeAaWjZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d88fuT/btrSZR3WPR9/ukhiF1qAm18GIHHeAaWjZk/img.png&quot; style=&quot;width: 38.2382%;&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;333&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;38.69&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d88fuT/btrSZR3WPR9/ukhiF1qAm18GIHHeAaWjZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd88fuT%2FbtrSZR3WPR9%2FukhiF1qAm18GIHHeAaWjZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;355&quot; height=&quot;333&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;conda 가산환경 (env_test)를 활성화 하고, 설치 패키지를 확인하면, torch는 정상 설치되어 있다. (좌), Jupyter Notebook에서 `pip list`를 실행하면 무엇인가 설치된 패키지가 다르다. (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;무엇인가 잘못된것 같다.&lt;br /&gt;무슨일이 일어난 것일까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;우선 conda 가상환경 목록을 먼저 살펴보자. `conda env list` 명령을 통하여 생성되어 있는 가상환경 목록을 나열할 수 있다. 다음으로 Jupyter Kernel 목록을 나열하기 위해 `jupyter kernelspec list`명령어를 사용하자.&amp;nbsp; 각 명령어를 사용하면, 가상환경과 가상환경이 설치된 경로를, Jupyter Kernel 과 Kernel의 설정파일 경로를 확인할 수 있다.&amp;nbsp; 명령을 실행 후 알 수 있듯이, conda 가상환경은 Anaconda 패키지 하위에, jupyter Kernel은 Users home 하위 Jupyter/kernels 하위에 위치해 있다. 두 경로간의 연계성은 전혀 존재하지 않는다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음은 conda env와 jupyter kernelspec 을 통해서 각각 가상환경이 설치된 위치를 확인한다.&lt;/h4&gt;
&lt;pre id=&quot;code_1670330069001&quot; class=&quot;vala&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda env list
# conda environments:
#
# base                  *  /Users/richwind/opt/anaconda3
# env_test                 /Users/richwind/opt/anaconda3/envs/env_test

$ jupyter kernelspec list
#  env_test    /Users/richwind/Library/Jupyter/kernels/env_test
#  python3     /Users/richwind/Library/Jupyter/kernels/python3&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;conda 가상환경의 위치와 Jupyter Kernel의 위치가 서로 상이함을 알 수 있다. 즉, conda 가상환경과 이름이 동일한 또다른 Jupyter 가상환경이 생성되었을 뿐을 의미한다. 따라서, 이전 섹션에서 살펴본 봐와 같이 conda에서 설치한 패키지가 Jupyter Notebook의 Kernel에서는 동작하지 않는 것이다.&amp;nbsp; ( 가상환경 이름 : env_test, Kernel name : env_test를 가정)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;conda 가상환경 : /Users/richwind/opt/anaconda3/envs/env_test&lt;/li&gt;
&lt;li&gt;jupyter kernel : /Users/richwind/Library/Jupyter/kernels/env_test&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[ Jupyter kernel 목록 보기 ]&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1670315373460&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ jupyter kernelspec list
# Available kernels:
#  python3    /Users/richwind/Library/Jupyter/kernels/python3&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[ Jupyter kernel 추가하기 ]&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1670315610070&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ pip install ipykernel
$ python -m ipykernel install --user --name=env_test --display-name=env_test

# Installed kernelspec env_test in /Users/richwind/Library/Jupyter/kernels/env_test&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Jupyter 커널 추가후, 다시 커널 목록을 확인하자. env_test 라는 이름의 커널이 추가 되어 있는것을 확인 할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1670315740351&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ jupyter kernelspec list

# Available kernels:
#  env_test    /Users/richwind/Library/Jupyter/kernels/env_test
#  python3     /Users/richwind/Library/Jupyter/kernels/python3&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;따라서, JupyterLab 혹은 Jupyter Notebook UI에서 이제 &quot;env_test&quot;라는 이름의 커널/가상환경을 선택할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;conda 가상환경과 Jupyter Kernel을 연동하고, 패키지 설치/관리는 conda 환경으로 하면 동시에 Jupyter에 반영되도록 하는 방법을 추가 설명한다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;가상환경 연동 Jupyter Kernel 생성 (기존 존재 경우 Overwrite)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기존 conda 환경에서 Jupyter Notebook Kernel을 연결해 주는 패키지 (nb_conda_kernels)를 설치한다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1670323812864&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda install -c conda-forge nb_conda_kernels&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;구글검색에 의하면, `pip install nb_conda` 설치도 가능하다고 한다. 필자의 환경에서는 동작하지 않았다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;패키지(nb_conda_kernels)를 설치 후, 가상환경을 활성화(activate)하고, `ipython kernel install`을 통해서 Jupyter Kernel을 생성해 준다. 이 때 `--name=&amp;lt;가상환경 이름&amp;gt;`으로 선택해 주어 conda 가상환경과 Jupyter Kernel을 연결해 준다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1670317651776&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda activate env_test
$ ipython kernel install --user --name=env_test
#Installed kernelspec env_test in /Users/richwind/Library/Jupyter/kernels/env_test


# 위 경우가 안될 경우,
$ conda activate env_test
$ conda install ipykernel
$ python -m ipykernel install --user --name=env_test
#Installed kernelspec env_test in /Users/richwind/Library/Jupyter/kernels/env_test&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;jupyter kernel 삭제 : `jupyter kernelspec uninstall &amp;lt;커널이름&amp;gt;`. ex) jupyter kernelspec uninstall env_test&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음으로 Jupyter Notebook을 리프레시 or 재시작 해 주자. 다음 처럼 패키지가 설치된 가상환경으로 동작하는지 점검 해 볼 수 있다. 다음 예는 타겟 가상환경에만 `joblib`를 설치한 경우 Jupyter Notebook에서 joblib 설치 여부를 확인하는 경우이다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1670324091311&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;%pip list | grep joblib&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;좀 더 상세하게, 이러한 행위는 결과적으로 Jupyter 커널 설정파일 (kernel.json)의 argv값을 변경해 주는 것이다. kernel.json 파일은&amp;nbsp; Jupyter 설치 폴더 아래 `kernels/&amp;lt;kernel name&amp;gt;/kernel.json`에 위치한다. 다음은 kernel.json의 내용이다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1670323095113&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ cat  ~/Library/Jupyter/kernels/env_test/kernel.json

{
 &quot;argv&quot;: [
  &quot;/Users/richwind/opt/anaconda3/envs/env_test/bin/python&quot;,
  &quot;-m&quot;,
  &quot;ipykernel_launcher&quot;,
  &quot;-f&quot;,
  &quot;{connection_file}&quot;
 ],
 &quot;display_name&quot;: &quot;env_test&quot;,
 &quot;language&quot;: &quot;python&quot;,
 &quot;metadata&quot;: {
  &quot;debugger&quot;: true
 }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;앞서 거론한 바와 같이, conda 가상환경 파일과, Jupyter Kernel의 경로는 다르게 지정되어 있으므로, jupyter kernel.json에서는 가상환경 아래 python 파일 위치를 지정함으로써 해당 가상환경으로 동작하도록 설정해주는 작업니다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적으로, argv의 첫번째 매개변수가 base의 python이다. PATH가 제대로 걸려 있으면, 단순히 &quot;python&quot;이 기본값이다.&amp;nbsp; &quot;display_name&quot;등도 여기에 설정되어 있다. 만약, 이런 저런것이 번거롭다면, `kernel.json`을 수동으로 설정 해 주어도 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;python 가상환경은 결국, 다른 python root directory에 패키지 설치를 다시 한 환경이므로, 가상환경용 python 실행 파일로 실행하면, 가상환경으로 동작할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Linux 환경 등에서 jupyter kernel.json 기본설정은 아래와 같다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1670324765442&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat /usr/local/share/jupyter/kernels/python3/kernel.json 
{
 &quot;argv&quot;: [
  &quot;python&quot;,
  &quot;-m&quot;,
  &quot;ipykernel_launcher&quot;,
  &quot;-f&quot;,
  &quot;{connection_file}&quot;
 ],
 &quot;display_name&quot;: &quot;Python 3 (ipykernel)&quot;,
 &quot;language&quot;: &quot;python&quot;,
 &quot;metadata&quot;: {
  &quot;debugger&quot;: true
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Jupyter Kernel 추가] conda 가상환경을 jupyter Kernel로 추가하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/207&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.09.19 - [개발 이야기/Python] - [주피터노트북 커널] jupyter lab/notebook kernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/126&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2020.06.04 - [개발 이야기/Python] - [파이썬] Anaconda x Jupyter notebook 설치 및 설정 방법 - 가상환경으로 파이썬 개발환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/19&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2020.03.10 - [IT 이야기] - Python x Jupyter Notebook 설치 및 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/206&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.09.19 - [IT 이야기/IT 상식] - [Python 가상환경] conda 설치 및 가상환경 (feat. 내부 로직 &amp;amp; cheat sheet)&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발 이야기/Python</category>
      <category>conda env</category>
      <category>conda jupyater 연결</category>
      <category>conda jupyter</category>
      <category>conda 가상환경 추가</category>
      <category>jupyter kernel 삭제</category>
      <category>jupyter kernel 생성</category>
      <category>Jupyter Kernel 설정</category>
      <category>jupyter kernel 추가</category>
      <category>nb_conda</category>
      <category>Python 가상환경과 jupyter 연동</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/212</guid>
      <comments>https://windflex.tistory.com/212#entry212comment</comments>
      <pubDate>Tue, 6 Dec 2022 20:17:35 +0900</pubDate>
    </item>
    <item>
      <title>[Mac OS] 배터리 충전 관리 (Charge limiter) - ft. AlDente</title>
      <link>https://windflex.tistory.com/211</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;필자는 MacBook을 DeskTop 처럼 사용한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이동용이라기 보다는 모니터 2대 + MacBook Screen (총 3대) 또는 크림쉘 모드로 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사실, Desktop이 있어도 잘 사용을 안해서 처분 했다.&amp;nbsp; 게임도 잘 안하는 지라... 게임할 때는 전용 게임기로..&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이렇듯 나에게 있어서 MacBook은 이동용이 아니기 때문에 대부분의 시간에 전원 케이블 (Mac Safe)이 연결되어 있다. 따라서 당연하게도 Mac OS에서 충전 배터리 관리를 잘 해줄 것으로 믿고 항시 전원 케이블 연결로 사용해 왔었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size18&quot; data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #9feec3;&quot;&gt;리튬 배터리를 사용할 텐데, 배터리 충전 관리는 알아서 해 주겠지...?&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;당연하지... 스마트하게 배터리 충전 관리 해 주지..&lt;br /&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;정말 ??&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;516&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZHBCS/btrQuIoqN76/gsa0kKBkaTMYiGSuJxms6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZHBCS/btrQuIoqN76/gsa0kKBkaTMYiGSuJxms6K/img.png&quot; data-alt=&quot;맥북 Ventura 지원, 배터리 관리 최적화 - 배터리 충전 제한 (AlDente)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZHBCS/btrQuIoqN76/gsa0kKBkaTMYiGSuJxms6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZHBCS%2FbtrQuIoqN76%2Fgsa0kKBkaTMYiGSuJxms6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;599&quot; height=&quot;516&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;516&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;맥북 Ventura 지원, 배터리 관리 최적화 - 배터리 충전 제한 (AlDente)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Mac OS의 배터리 관리 기능 - 배터리 최적화&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Mac OS Ventura의 배터리 메뉴 (설정 &amp;gt; 배터리 &amp;gt; 배터리 성능 상태 &amp;gt; 오른쪽 &quot;i&quot; 클릭) 에도 확인해 보면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&quot;최적화된 배터리 충전&quot; 기능으로 스마트한 배터리 관리를 해 주고 있는 것으로 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;필자는 다음 섹션에서 소개할 배터리 충전 리미터를 사용하기 위해 일단 기능을 꺼 두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(만약, 충전 리미터를 사용하지 않으면 당연하게도 이 기능은 활성화 해 두어야 할것이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RF0G8/btrQAw1rlbY/uw2ahcXaPAZHK4UQ4L3C8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RF0G8/btrQAw1rlbY/uw2ahcXaPAZHK4UQ4L3C8K/img.png&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;650&quot; data-is-animation=&quot;false&quot; style=&quot;width: 31.1214%; margin-right: 10px;&quot; data-widthpercent=&quot;31.49&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RF0G8/btrQAw1rlbY/uw2ahcXaPAZHK4UQ4L3C8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRF0G8%2FbtrQAw1rlbY%2Fuw2ahcXaPAZHK4UQ4L3C8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;490&quot; height=&quot;650&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YmB65/btrQsDgNuCN/HXVdbKzQu4J17aHC2M82WK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YmB65/btrQsDgNuCN/HXVdbKzQu4J17aHC2M82WK/img.png&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;303&quot; data-is-animation=&quot;false&quot; style=&quot;width: 67.7158%;&quot; data-widthpercent=&quot;68.51&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YmB65/btrQsDgNuCN/HXVdbKzQu4J17aHC2M82WK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYmB65%2FbtrQsDgNuCN%2FHXVdbKzQu4J17aHC2M82WK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;497&quot; height=&quot;303&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Mac OS 배터리 관리 기능 - 최적화된 배터리 충전&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그런데, 그 스마트함 이라는 내용을 잘 읽어보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;일단 내용에서 알 수 있는 사항은,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배터리의 일상적인 충전이 80% 넘기면 배터리 수명이 단축된다는 것. --&amp;gt; 이미 Fact 이기 때문에, 인정하고 있음.(하드웨어적으로 무엇을 기대하기는 어려운듯 하다.)&lt;/li&gt;
&lt;li&gt;80%를 넘어가면 잠시 대기를 하고 있다가 나중에 사용자의 패턴에 맞추어 추가 충전 해 주겠다는 내용.&lt;br /&gt;(즉, 평시 행동 양식/패턴을 학습하고 그에 맞게 80%까지 충전하거나 Full 충전하거나 하겠다는 것이다. )&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다음은 애플의 공식 홈페이지에 배터리 관리에 대한 공식 문구 이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAOxeV/btrQywtYTDZ/XPawlgLLP1cF7fNknSgtMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAOxeV/btrQywtYTDZ/XPawlgLLP1cF7fNknSgtMK/img.png&quot; data-alt=&quot;애플의 공식 홈페이지. mac book의 배터리 관리 :&amp;amp;amp;nbsp;https://support.apple.com/ko-kr/guide/macbook-pro/apdbc13fd966/mac&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAOxeV/btrQywtYTDZ/XPawlgLLP1cF7fNknSgtMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAOxeV%2FbtrQywtYTDZ%2FXPawlgLLP1cF7fNknSgtMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;627&quot; height=&quot;359&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;애플의 공식 홈페이지. mac book의 배터리 관리 :&amp;amp;nbsp;https://support.apple.com/ko-kr/guide/macbook-pro/apdbc13fd966/mac&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7Z9OE/btrQxbqs3uF/dZ4ByvKbIrd3Xrf2qYAtvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7Z9OE/btrQxbqs3uF/dZ4ByvKbIrd3Xrf2qYAtvk/img.png&quot; data-alt=&quot;배터리 화학적 노화를 방지하기 위해, 배터리 충전 패턴을 반영하여 80% 충전을 유지하도록 최적화 한다고 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7Z9OE/btrQxbqs3uF/dZ4ByvKbIrd3Xrf2qYAtvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7Z9OE%2FbtrQxbqs3uF%2FdZ4ByvKbIrd3Xrf2qYAtvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;621&quot; height=&quot;125&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;배터리 화학적 노화를 방지하기 위해, 배터리 충전 패턴을 반영하여 80% 충전을 유지하도록 최적화 한다고 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;필자는 외출/Offline Meeting/사무실 출근 (평시 재택)에만 mac의 배터리 기능을 필요로 한다. 그 외에 모든 시간은 전원을 사용한다. 그런데, 내가 외출할 것을 알 수 있을까?? (참고로 필자는 15년 이상 Machine Learning 업무를 하고 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;특별히, 출근/외출 패턴이 있지 않거나, 내 일정 정보를 입력해 두지 않는한 나의 외출에 맞추어 배터리를 충전 할 수 는 없을듯 한다.&amp;nbsp; 위에서 이야기하는 사용자 충전 패턴이라는 것은, 평시 충전케이블을 꽂아 두는가? 밤사이에는 충전을 할것인가? 아침 작업시간 (9:00)에 맞추어 충전을 해 둘것인가? 등의 스케줄링이라고 판단할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;흐음.. 그럼, 하드웨어적으로 100% 충전을 막는 최소한의 장치를 제외하면, 나의 경우에는 대부분 최대충전상태(Full Charge)로 유지 된다는 결론이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이런 내용을 종합해 보았을 때, 필자의 판단은,,,,&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size18&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;흐음.. 배터리 관리 좀 어색한데??&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;최소한, 애플의 배터리 최적화를 어느 정도 믿는다고 할 지라도, 새로운 맥북의 초기는 잘 관리해 주어야 할 필요성이 느껴진다.그렇다고, 어느정도 충전이 되었을 때마다, 충전케이블을 뺐다 꼈다 하는 것은 너무 번거로울뿐 아니라, 오히려 충전패턴의 오해로 인하여 과충전될 우려도 있다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;배터리 충전 리미터 - AlDente&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;처음에는 배터리 충전을 차단하는 Apple의 API가 있을 것으로 생각하고, 간단한 Application을 하나 만들어 둘까 했었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나, 잠깐 검색해 보니, 해당 기능을 수행해 주는 Open Source들이 몇 존재하더라. 역시 사람의 생각은 다 거기서 거기 인것 같다. &lt;u&gt;&lt;b&gt;그냥 가져다 쓰자.!&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;구글링 하면 관련된 기능을 가진 App은 다음과 같다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AlDente : &lt;a href=&quot;https://github.com/davidwernhart/AlDente&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/davidwernhart/AlDente&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;BatteryStatusShow : &lt;a href=&quot;https://github.com/sicreative/BatteryStatusShow&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/sicreative/BatteryStatusShow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Charge Limiter : &lt;a href=&quot;https://github.com/godly-devotion/charge-limiter/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/godly-devotion/charge-limiter/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;필자는 이 중에서 M1 Chip을 지원하고, Ventura를 지원하며, 가장 일반적이라서 문제 발생 시 해결이 쉬울것으로 생각되는 App.를 선택하였다. 결론은 알덴테(AlDente) - 이렇게 읽는게 맞나??&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈 소스이기도 하지만 상용화 하고 있는 것 같다. 다음 사이트에서 무료 버전을 다운로드 받을 수 있다. 가격 정책에 따라서 여러가지 기능을 추가로 제공하는데, 필자는 충전 제한 기능이 필요한 것이므로 무료버전으로 충분할 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AlDente 무료 버전 다운로드 : &lt;a href=&quot;https://apphousekitchen.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://apphousekitchen.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ssPsG/btrQuIPunuC/gfqKF6mlOpHnHAFIouzZqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ssPsG/btrQuIPunuC/gfqKF6mlOpHnHAFIouzZqK/img.png&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;636&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.8494%; margin-right: 10px;&quot; data-widthpercent=&quot;52.46&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ssPsG/btrQuIPunuC/gfqKF6mlOpHnHAFIouzZqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FssPsG%2FbtrQuIPunuC%2FgfqKF6mlOpHnHAFIouzZqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;796&quot; height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmelsx/btrQuNJWDVt/BaIypvqWshxAaOGoOJe1h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmelsx/btrQuNJWDVt/BaIypvqWshxAaOGoOJe1h0/img.png&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;976&quot; data-is-animation=&quot;false&quot; style=&quot;width: 46.9878%;&quot; data-widthpercent=&quot;47.54&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmelsx/btrQuNJWDVt/BaIypvqWshxAaOGoOJe1h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbmelsx%2FbtrQuNJWDVt%2FBaIypvqWshxAaOGoOJe1h0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1107&quot; height=&quot;976&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AlDente 무료 버전 설치 (좌), 가격 정책별 기능 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Application을 설치하고나면, 상단 메뉴에 스파게티 모양의 새로운 아이템이 추가 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;AlDente 사용 설정을 위해서 2단계가 필요하다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1) Mac OS 기본 설정인 &quot;최적화된 배터리 충전&quot; 기능을 비활성화 한다.&amp;nbsp; --&amp;gt; Mac OS의 설정이 AlDente 설정보다 우선 하기 때문.&lt;/li&gt;
&lt;li&gt;2) AlDente 메뉴에서 &quot;충전 한도&quot;를 설정한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 단계 1)의 Mac OS 기본 설정을 비활성화 하는 화면이다. 설정 &amp;gt; 배터리 &amp;gt; 배터리 성능 상태의 우측 &quot;i&quot;아이콘 클릭 &amp;gt; 최적화된 배터리 충전 기능 Off.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;805&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btWxAK/btrQr7oSM6A/ligbUoJCCI6Rk1vV7qT0ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btWxAK/btrQr7oSM6A/ligbUoJCCI6Rk1vV7qT0ck/img.png&quot; data-alt=&quot;Mac OS &amp;quot;최적화된 배터리 충전&amp;quot;기능 비활성화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btWxAK/btrQr7oSM6A/ligbUoJCCI6Rk1vV7qT0ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtWxAK%2FbtrQr7oSM6A%2FligbUoJCCI6Rk1vV7qT0ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;713&quot; height=&quot;805&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;805&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mac OS &quot;최적화된 배터리 충전&quot;기능 비활성화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음, 단계 2)로써 상단 메뉴에서 AlDente 아이콘 (스파게티 모양)을 클릭하고 충전 한도를 설정한다. 필자는 아래와 같이 70% 충전 제한으로 설정하였다. 이로써 2시간 넘게 충전케이블을 꽂아 두었지만 배터리가 71% 상태에서 멈추어 있는 것을 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;395&quot; data-origin-height=&quot;143&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddsrtQ/btrQxaSchnE/IYRMWQL4CVc36dbtiKCGT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddsrtQ/btrQxaSchnE/IYRMWQL4CVc36dbtiKCGT0/img.png&quot; data-alt=&quot;AlDente 메뉴와 설정 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddsrtQ/btrQxaSchnE/IYRMWQL4CVc36dbtiKCGT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddsrtQ%2FbtrQxaSchnE%2FIYRMWQL4CVc36dbtiKCGT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;395&quot; height=&quot;143&quot; data-origin-width=&quot;395&quot; data-origin-height=&quot;143&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AlDente 메뉴와 설정 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;유료 기능을 잠깐 살펴보면, Pro Version의 경우 아래와 같은 추가 기능을 제공한다. (뭐.. 필자는 기본 기능 만으로도 O.K.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kDGe0/btrQywVrIiO/nqkWhB5MwXw8IsH9ikcO50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kDGe0/btrQywVrIiO/nqkWhB5MwXw8IsH9ikcO50/img.png&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;567&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.1391%; margin-right: 10px;&quot; data-widthpercent=&quot;47.69&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kDGe0/btrQywVrIiO/nqkWhB5MwXw8IsH9ikcO50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkDGe0%2FbtrQywVrIiO%2FnqkWhB5MwXw8IsH9ikcO50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;428&quot; height=&quot;567&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wZtLq/btrQvNXIPuo/OkKBfrZTPI2FPRjQpWnHq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wZtLq/btrQvNXIPuo/OkKBfrZTPI2FPRjQpWnHq1/img.png&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;517&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.6981%;&quot; data-widthpercent=&quot;52.31&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wZtLq/btrQvNXIPuo/OkKBfrZTPI2FPRjQpWnHq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwZtLq%2FbtrQvNXIPuo%2FOkKBfrZTPI2FPRjQpWnHq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;428&quot; height=&quot;517&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AlDente의 Pro Version 유료 기능들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;[개인적인 추천 설정]&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적인 설정 방안을 공유 해 본다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AlDente를 사용함에 있어서 하나의 문제점이 있다. Application이 동작하고 있지 않을 때는 배터리 관리가 불가능할 수 있다는 것이다. 즉, AlDente 서비스가 죽어버린 경우, 배터리 관리가 방치된다는 것이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;우리는 앞서, Mac OS의 배터리 최적화 관리 기능을 Off해 두었다. 따라서, 만약 AlDente 서비스가 종료되어 있고, 배터리 케이블은 충전으로 되어 있다면, 배터리 관리가 완전히 방치 되어 버리게 되는 것이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 Risk가 있기 때문에, 필자는 개인적으로 아래 2가지 옵션을 사용한다. (순수히 개인적인 설정이다.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;&lt;u&gt;&lt;b&gt;설정 1) AlDente 설정 &amp;gt; 일반적인 &amp;gt; 기타 &amp;gt; &quot;시작 시 자동 실행&quot;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;개인적으로는 로그인 할 때 자동으로 실행하도록 설정하는 것이 좋을것으로 판단하였다. 그 이유는 앞서 설명한 바와 같이 Mac OS의 기본 배터리 관리 기능을 Off하였다. 따라서, AlDente가 꺼져 있고, mac os의 기본 배터리 관리 기능도 꺼져 있다면, 아무런 배터리 관리 기능이 동작하고 있지 않을 수 있기 때문이다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;&lt;u&gt;설정 2) Mac OS의 &quot;최적화된 배터리 충전&quot;을 Off 하고 난 다음, &quot;내일까지 끄기&quot; 선택&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;이후 생각이 날때 다시 Off&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;width:36.559465328999764%&quot; src=&quot;https://blog.kakaocdn.net/dn/bMGuEM/btrQC78JY7W/17ckqnMkeGI4ZbWFoju1kK/img.png&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;447&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;36.99&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvinGb/btrQBMjBt3b/AlYHGQxAZ4X3s3bnf74cr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvinGb/btrQBMjBt3b/AlYHGQxAZ4X3s3bnf74cr1/img.png&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;527&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.8033%; margin-right: 10px;&quot; data-widthpercent=&quot;33.19&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvinGb/btrQBMjBt3b/AlYHGQxAZ4X3s3bnf74cr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvinGb%2FbtrQBMjBt3b%2FAlYHGQxAZ4X3s3bnf74cr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;428&quot; height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b19bS2/btrQxbqQdK2/B4X2jMZdUHqyeJVQiexgz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b19bS2/btrQxbqQdK2/B4X2jMZdUHqyeJVQiexgz1/img.png&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;304&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;66.81&quot; style=&quot;width: 66.0339%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b19bS2/btrQxbqQdK2/B4X2jMZdUHqyeJVQiexgz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb19bS2%2FbtrQxbqQdK2%2FB4X2jMZdUHqyeJVQiexgz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;497&quot; height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;설정 1) AlDente &quot;시작 시 자동 실행&quot; 기능 활성화 (좌), 설정 2) mac os 기본 최적화 배터리 충전 기능 &amp;gt; 내일까지 끄기 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;[주의 할점 ] 설치 삭제 및 원복&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;알려진 주의 할점을 하나 언급 해봅니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;때로는 이러한 방식이 적합하지 않거나 필요 없을 때, 삭제하게 될 것인데요. 삭제할 때 유의할 점입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;(공식 홈이나 다른분들의 리뷰에 적혀 있는 부분입니다만, 제가 삭제 테스트 할 때는 그냥 삭제해도 문제가 되지 않았습니다. 참조바랍니다. )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size18&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; 이 때, 삭제 전에 충전 한도를 100%로 원복&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;충전 한도 (Charge Limit)는 다시 100%로 맞추어 주자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;개발 경험이 있는 분들이라면, 이해 할것이다. 아마도 이러한 충전 한도의 기록은 OS의 어딘가에 Config 형태 또는, API Event의 파라미터로 남아 있을 것이다. 삭제하는 시점에 자동으로 이 Config를 복원해 주면 좋을 텐데, 그렇게 하지 못하나 보다. 이게 여전히 70% 등으로 남아 있다면, 계속 배터리를 70%만 충전해서 사용하는 상태가 지속 될 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;만약, 이미 삭제 했다면, AlDente를 다시 설치하고, 100%로 수정 한 다음 다시 삭제를 해 주도록 하자.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;그리고, 삭제 후 안정적인 설정 변경/적용을 위해서, 리부팅을 한번 실행해 주면 깔끔하겠다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;(추가) 객관화한 배터리 상태 확인하기 - Battery Monitory&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;물리적인 배터리의 상태 (Mac OS가 해석해 주는 상태 말고)를 확인하기 위해서는 아래 App.를 추천한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;App. 이름 : Battery Monitor&lt;/li&gt;
&lt;li&gt;Apple Store에서 Battery Monitor 혹은 배터리 관리 라고 검색하면 찾을 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5lXpE/btrQsC95mSS/Znh18IOBUj3suahxVRMfkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5lXpE/btrQsC95mSS/Znh18IOBUj3suahxVRMfkk/img.png&quot; data-alt=&quot;Battery Monitor App. App store에서 배터리 관리로 검색해 보자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5lXpE/btrQsC95mSS/Znh18IOBUj3suahxVRMfkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5lXpE%2FbtrQsC95mSS%2FZnh18IOBUj3suahxVRMfkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;456&quot; height=&quot;354&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Battery Monitor App. App store에서 배터리 관리로 검색해 보자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배터리의 객관적인 현재 상태를 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Yynka/btrQtSSkMfS/GkBTKCzpf9J45mGluLhMA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Yynka/btrQtSSkMfS/GkBTKCzpf9J45mGluLhMA0/img.png&quot; data-alt=&quot;배터리의 물리적인 상태를 mAh 단위로 확인할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Yynka/btrQtSSkMfS/GkBTKCzpf9J45mGluLhMA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYynka%2FbtrQtSSkMfS%2FGkBTKCzpf9J45mGluLhMA0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;282&quot; height=&quot;268&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;배터리의 물리적인 상태를 mAh 단위로 확인할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;[ 관련 글]&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/210&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.11.07 - [IT 이야기/IT 상식] - [맥북 Ventura] 배터리 잔량 퍼센트 보기 - ft. 제어 센터&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/209&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.10.31 - [IT 이야기/IT 상식] - [MacOS] 백틱(`) 입력 - 원화(₩)입력 변경 to BQuote(`)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/208&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.10.20 - [IT 이야기/IT 상식] - [MacOS - ZSH] 유용한 플러그인 2종 - 자동완성/하이라이트&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/202&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.07.25 - [IT 이야기] - [Mac+Chrome] 구글 독스 한글 깨짐 현상 (자/모분리)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/195&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.06.29 - [IT 이야기/IT 상식] - [맥북-NTFS] 맥북에서 윈도우 외장하드(NTFS) 쓰기(mount) - 모든버전 사용 가능&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/157&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.01.21 - [IT 이야기/IT 상식] - 맥(MacOS)에서 특수문자/한자 입력 하기 -☆ ★ ○ ●&lt;/a&gt;&lt;/p&gt;</description>
      <category>IT 이야기</category>
      <category>Aldente</category>
      <category>AlDente 삭제</category>
      <category>Battery Limit</category>
      <category>맥북 배터리</category>
      <category>맥북 배터리 관리</category>
      <category>맥북 배터리 충전 제한</category>
      <category>배터리 80% 제한</category>
      <category>배터리 모니터</category>
      <category>배터리 최적화</category>
      <category>배터리 충전 리미터</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/211</guid>
      <comments>https://windflex.tistory.com/211#entry211comment</comments>
      <pubDate>Mon, 7 Nov 2022 12:28:52 +0900</pubDate>
    </item>
    <item>
      <title>[맥북 Ventura] 배터리 잔량 퍼센트 보기 - ft. 제어 센터</title>
      <link>https://windflex.tistory.com/210</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Mac OS Ventura - 다양한 UI 변화&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;최근 Mac OS Ventura로 OS 업그레이드를 진행했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그런데, 이전 업데이트 들과는 달리 Ventura에서는 UI가 상당수 많이 변경이 되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;특히, &quot;설정&quot; UI는 아예 다른 스타일로 변경이 되었습니다. 기존에는 바둑판식 UI 였습니다만, 이번 Ventura에서는 좌우 창을 나누고 왼쪽에 리스트 형태로 나열 되어 있는 형태로 바뀌었습니다. 마치 설정창 또한 Finder 같은 UI로 동일화 한것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;개인적으로는, 기존의 설정 UI가 익숙하고 좋았는데, Ventura도 나름 정리는 잘 되어 있는 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;PS. Ventura 업데이트에서 &quot;스마트 메니저&quot;, &quot;iOS 스크린 연동&quot; 등 큼직한 업데이트가 있어서 이번 Ventura 업데이트는 마음에 듭니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I2n8j/btrQz6BK94y/o8U2jkSSgd2DX5KnJI7wa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I2n8j/btrQz6BK94y/o8U2jkSSgd2DX5KnJI7wa0/img.png&quot; data-alt=&quot;배터리 잔량 퍼센트로 보기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I2n8j/btrQz6BK94y/o8U2jkSSgd2DX5KnJI7wa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI2n8j%2FbtrQz6BK94y%2Fo8U2jkSSgd2DX5KnJI7wa0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;배터리 잔량 퍼센트로 보기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;배터리 잔량을 숫자/퍼센트로 표기하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;각설하고, 설정 UI가 변경되다 보니, 기존에 사용하던 설정의 위치가 혼란 스럽습니다. 이번에는 배터리 관련된 사항인데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;베터리 기본설정은 숫자가 표기 되지 않습니다. 아래처럼 배터리 잔량이 숫자로 표기된 설정으로 바꾸려 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;23&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYISZj/btrQBLD5Q6Z/P4kakl7O5KDlpncC4u0Al0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYISZj/btrQBLD5Q6Z/P4kakl7O5KDlpncC4u0Al0/img.png&quot; data-alt=&quot;Mac OS Ventura 배터리 잔량 퍼센트 표기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYISZj/btrQBLD5Q6Z/P4kakl7O5KDlpncC4u0Al0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYISZj%2FbtrQBLD5Q6Z%2FP4kakl7O5KDlpncC4u0Al0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;544&quot; height=&quot;23&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;23&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mac OS Ventura 배터리 잔량 퍼센트 표기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기존 Monterey 까지만 해도 &quot;설정 &amp;gt; 배터리&quot;에 가면 &quot;퍼센트 보기&quot;라는 스위치가 있었습니다. 그러나, Ventura에서는 해당 메뉴를 찾을 수 없네요. 아래처럼 설정&amp;gt; 배터리를 가면 단순하게 배터리 잔량 모니터링/사용률, 그리고 저전력 모드에 대한 설정만 존재합니다. 옵션을 눌러봐도 딱히 퍼센트 보기를 찾을 수 없습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;807&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFhRRc/btrQrEHbzKA/uo76CK1clgjOE63VH7zQTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFhRRc/btrQrEHbzKA/uo76CK1clgjOE63VH7zQTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFhRRc/btrQrEHbzKA/uo76CK1clgjOE63VH7zQTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFhRRc%2FbtrQrEHbzKA%2Fuo76CK1clgjOE63VH7zQTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;706&quot; height=&quot;807&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;807&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상단의 메뉴바를 클릭하면 배터리 설정이 나오는데, 여기에서 &quot;배터리 설정...&quot;을 클릭해도 위의 배터리 메뉴가 열리게 됩니다. &quot;퍼센트 보기&quot;는 어디로 갔을까??&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BxNJR/btrQvZpNFFB/XLq0MSKqat64Gzeum8kKXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BxNJR/btrQvZpNFFB/XLq0MSKqat64Gzeum8kKXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BxNJR/btrQvZpNFFB/XLq0MSKqat64Gzeum8kKXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBxNJR%2FbtrQvZpNFFB%2FXLq0MSKqat64Gzeum8kKXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;297&quot; height=&quot;168&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Mac OS Ventura에서는 메뉴의 구성들이 소폭 변경되어서 찾기 어려웠는데요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위치는 &lt;u&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&quot;설정 &amp;gt; 제어 센터 &amp;gt; 배터리&quot;에 &quot;퍼센트 보기&quot;&lt;/span&gt; &lt;/b&gt;&lt;/u&gt;메뉴가 있습니다. 아무리 배터리 관련한 설정이라도 메뉴 관련된 사항은 제어센터에 따로 모아놨네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;883&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l0lva/btrQsD16Qhh/tpiqKMqyvlyhh05VzMfzDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l0lva/btrQsD16Qhh/tpiqKMqyvlyhh05VzMfzDk/img.png&quot; data-alt=&quot;설정 &amp;amp;gt; 제어 센터 &amp;amp;gt; 배터리 &amp;amp;gt; 퍼센트 보기 에 배터리 잔량을 수치로 표현하는 기능이 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l0lva/btrQsD16Qhh/tpiqKMqyvlyhh05VzMfzDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl0lva%2FbtrQsD16Qhh%2FtpiqKMqyvlyhh05VzMfzDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;762&quot; height=&quot;883&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;883&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;설정 &amp;gt; 제어 센터 &amp;gt; 배터리 &amp;gt; 퍼센트 보기 에 배터리 잔량을 수치로 표현하는 기능이 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;[ 관련 글]&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/211&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.11.07 - [IT 이야기] - [Mac OS] 배터리 충전 관리 (limiter) - ft. AlDente&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/210&quot;&gt;2022.11.07 - [IT 이야기/IT 상식] - [맥북 Ventura] 배터리 잔량 퍼센트 보기 - ft. 제어 센터&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/209&quot;&gt;2022.10.31 - [IT 이야기/IT 상식] - [MacOS] 백틱(`) 입력 - 원화(₩)입력 변경 to BQuote(`)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/208&quot;&gt;2022.10.20 - [IT 이야기/IT 상식] - [MacOS - ZSH] 유용한 플러그인 2종 - 자동완성/하이라이트&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/202&quot;&gt;2022.07.25 - [IT 이야기] - [Mac+Chrome] 구글 독스 한글 깨짐 현상 (자/모분리)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/195&quot;&gt;2022.06.29 - [IT 이야기/IT 상식] - [맥북-NTFS] 맥북에서 윈도우 외장하드(NTFS) 쓰기(mount) - 모든버전 사용 가능&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/157&quot;&gt;2021.01.21 - [IT 이야기/IT 상식] - 맥(MacOS)에서 특수문자/한자 입력 하기 -☆ ★ ○ ●&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>Mac OS 배터리 퍼센트 보기</category>
      <category>Ventura 배터리 설정</category>
      <category>Ventura 배터리 잔량 수치 보기</category>
      <category>Ventura 배터리 잔량 표시</category>
      <category>배터리 잔량 수치 보기</category>
      <category>배터리 잔량 표시하기</category>
      <category>배터리 퍼센트 보기</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/210</guid>
      <comments>https://windflex.tistory.com/210#entry210comment</comments>
      <pubDate>Mon, 7 Nov 2022 10:14:13 +0900</pubDate>
    </item>
    <item>
      <title>[MacOS] 백틱(`) 입력 - 원화(₩)입력 변경 to BQuote(`)</title>
      <link>https://windflex.tistory.com/209</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;신규 맥북을 구매하거나 다시 설치하고 나면&lt;br /&gt;여러가지 설정이 초기화 된다.&lt;br /&gt;가령, 백틱 (`) 입력이 제대로 되지 않는 등의 일 말이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;맥북에서 백틱(`)으로 입력을 어떻게 해야 하나?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Mac OS를 새롭게 설치 혹은 맥북을 이제 막 구매하면, MacOS는 한글에 최적화 되어 잇는 것은 아니라는 것을 알 수 있다. 따라서, 기존에 사용하던 습관 그대로 사용하려면 몇가지 설정을 수정해 주어야 한다. 대표적인 예로, 한글 입력 모드에서 백쿼테이션(백틱`) 입력이 되지 않는 것을 예로 들 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;399&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFuj1f/btrP0fAoCBD/CtJtK9bdUZ11wFcRZdDLE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFuj1f/btrP0fAoCBD/CtJtK9bdUZ11wFcRZdDLE1/img.png&quot; data-alt=&quot;한글 입력 모드에서 백틱을 입력하면 원화표기(₩)가 입력된다. 백쿼테이션을 입력은 어떻게 해야 하나...?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFuj1f/btrP0fAoCBD/CtJtK9bdUZ11wFcRZdDLE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdFuj1f%2FbtrP0fAoCBD%2FCtJtK9bdUZ11wFcRZdDLE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;399&quot; height=&quot;422&quot; data-origin-width=&quot;399&quot; data-origin-height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;한글 입력 모드에서 백틱을 입력하면 원화표기(₩)가 입력된다. 백쿼테이션을 입력은 어떻게 해야 하나...?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;특히, 마크다운(Markdown)을 자주 사용하거나, Slack/Attlasian 등 마크다운 스타일 입력을 지원하는 업무용 툴을 사용함에 있어서 백틱의 입력 부재는 매우 불편함을 유발한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;맥북 원화표기(₩)를 백틱(`)으로 입력 - 키바인딩(KeyBinding)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;해결방법으로, 다음과 같이 Mac 사용자의 시작 설정에 원화표기(₩)를 지우고 백틱(`)으로 변경하는 키바인딩을 해 준다.&lt;/p&gt;
&lt;pre id=&quot;code_1667199138448&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo mkdir ~/Library/KeyBindings
sudo cat &amp;lt;&amp;lt; EOF &amp;gt; ~/Library/KeyBindings/DefaultkeyBinding.dict
&amp;gt; {
&amp;gt;	&quot;₩&quot; = (&quot;insertText:&quot;, &quot;`&quot;);
&amp;gt; }
&amp;gt; EOF&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;&amp;gt;&quot; 표기는 Interactive한 입력을 표기한 것이다. 한줄 한줄 입력하면된다. 입력 종료는 마지작 EOF를 입력함으로써 종료한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 살펴보면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) ~/Library/ 하위에 &quot;KeyBindings&quot;라는 디렉토리를 생성한다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;* ~/Library는 사용자 계정마다 실행되는 라이브러리 묶음이라 할 수 있으며, KeyBinings는 mac os에서 지원해 주는 키 바인딩 기능을 제공하는 디렉터리이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) ~/Library/KeyBinings/에 &quot;DefaultkeyBining.dict&quot;라는 파일을 생성한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) ~/Library/KeyBinings/DefaultkeyBining.dict 내용으로 아래처럼 원화표기(₩)를 백틱(`)으로 대체하는 바인딩 설정을 처리한다.&lt;/p&gt;
&lt;pre id=&quot;code_1667199407091&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
	&quot;₩&quot; = (&quot;insertText:&quot;, &quot;`&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;여기까지 바인딩 설정을 해 주었다. 그러나, 아직 바인딩 설정이 로딩 된것은 아니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;사용자 계정 내의 응용프로그램이 시작되는 시점에 ~/Library/ 하위 디렉토리의 설정이 적용된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;따라서, 위 키바인딩이 적용되기 위해서는 각 프로그램을 종료하고 새로 시작될 때, 혹은 아예 mac OS가 다시 시작될 때 적용될 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;참고로, 응용프로그램의 탭이 새로 시작되었다고 적용되지는 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들면, terminal 등은 모든 창이 닫혀 있어서, terminal application은 아직 떠 있는 경우가 있는데, 이 경우 상단 macos 메뉴에서 프로그램 종료를 누른 후 다시 시작하면 적용 될 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이상 macos의 키바인딩을 이용한 원화표기(₩) --&amp;gt; 백틱(`)변경 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;[ 관련 글]&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/211&quot;&gt;2022.11.07 - [IT 이야기] - [Mac OS] 배터리 충전 관리 (limiter) - ft. AlDente&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/210&quot;&gt;2022.11.07 - [IT 이야기/IT 상식] - [맥북 Ventura] 배터리 잔량 퍼센트 보기 - ft. 제어 센터&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/209&quot;&gt;2022.10.31 - [IT 이야기/IT 상식] - [MacOS] 백틱(`) 입력 - 원화(₩)입력 변경 to BQuote(`)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/208&quot;&gt;2022.10.20 - [IT 이야기/IT 상식] - [MacOS - ZSH] 유용한 플러그인 2종 - 자동완성/하이라이트&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/202&quot;&gt;2022.07.25 - [IT 이야기] - [Mac+Chrome] 구글 독스 한글 깨짐 현상 (자/모분리)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/195&quot;&gt;2022.06.29 - [IT 이야기/IT 상식] - [맥북-NTFS] 맥북에서 윈도우 외장하드(NTFS) 쓰기(mount) - 모든버전 사용 가능&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/157&quot;&gt;2021.01.21 - [IT 이야기/IT 상식] - 맥(MacOS)에서 특수문자/한자 입력 하기 -☆ ★ ○ ●&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>bQuote</category>
      <category>mac os backtick</category>
      <category>`</category>
      <category>₩</category>
      <category>맥북 백틱 원화표기</category>
      <category>맥북 백틱 입력</category>
      <category>맥북 백틱 입력 방법</category>
      <category>백틱입력</category>
      <category>원화표기 백틱 변경</category>
      <category>원화표시 변경 방법</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/209</guid>
      <comments>https://windflex.tistory.com/209#entry209comment</comments>
      <pubDate>Mon, 31 Oct 2022 16:03:29 +0900</pubDate>
    </item>
    <item>
      <title>[MacOS - ZSH] 유용한 플러그인 2종 - 자동완성/하이라이트</title>
      <link>https://windflex.tistory.com/208</link>
      <description>&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;맥북 M1 Pro로 PC를 변경했습니다. 세팅할게 많네요 ^^&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/125&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2020.06.01 - [IT 이야기/IT 상식] - [맥북] 맥북 터미널을 이쁘게 - ZSH 초간단 설치와 커스터마이징 (zhs + iTerm2)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blL4Yi/btrPbaG1s2y/j70ObC7y4MXfcvTT1qBwl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blL4Yi/btrPbaG1s2y/j70ObC7y4MXfcvTT1qBwl1/img.png&quot; data-alt=&quot;ZSH 플러그인 : 자동완성 (AutoSuggestion), 하이라이트 (Syntax Highlighting)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blL4Yi/btrPbaG1s2y/j70ObC7y4MXfcvTT1qBwl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblL4Yi%2FbtrPbaG1s2y%2Fj70ObC7y4MXfcvTT1qBwl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ZSH 플러그인 : 자동완성 (AutoSuggestion), 하이라이트 (Syntax Highlighting)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;ZSH 의 유용한 플러그인 2종 - &lt;span style=&quot;color: #777777;&quot;&gt;AutoSuggestion, &lt;span style=&quot;color: #777777;&quot;&gt;Highlighting&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ZSH을 취향에 맞는 테마로 구성했다면, 몇가지 유용한 Plugin을 설치할 수 있다. 대표적으로, 자동 완성과 하이라이팅 플러그인 이다.&amp;nbsp; 거의 필수적으로 사용되는 플러그인이다. Oh-My-ZSH을 사용하는 경우, 매우 쉽게 Plugins 기능을 설치/적용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;1) 자동완성 플러그인 : AutoSuggestions&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;2) 하이라이팅 플러그인 : Syntax Highlighting&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치하고자 하는 각 플러그인의 기능을 먼저 살펴 보자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자동완성 (AutoSuggestions)&lt;/b&gt;는 아래와 같이 한번 타이핑한 명령어를 &quot;회색&quot;으로 미리 제안 해 주는 기능을 제공한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cey546/btrPehFCUMO/Zni5eZ2sy3jvYrLL9Uj5ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cey546/btrPehFCUMO/Zni5eZ2sy3jvYrLL9Uj5ok/img.png&quot; data-alt=&quot;AutoSuggestion&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cey546/btrPehFCUMO/Zni5eZ2sy3jvYrLL9Uj5ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcey546%2FbtrPehFCUMO%2FZni5eZ2sy3jvYrLL9Uj5ok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;968&quot; height=&quot;221&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AutoSuggestion&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하이라이팅 (Syntax Hightlighting) 플러그인은 아래와 같이 명령어와 문자열 등 문맥에 맞게 구분하여 색상을 달리 표현해 주는 기능을 제공한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;95&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MtsV8/btrPfmr7rcS/rt4q1WgPoRaw7lfmVYNuT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MtsV8/btrPfmr7rcS/rt4q1WgPoRaw7lfmVYNuT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MtsV8/btrPfmr7rcS/rt4q1WgPoRaw7lfmVYNuT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMtsV8%2FbtrPfmr7rcS%2Frt4q1WgPoRaw7lfmVYNuT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;294&quot; height=&quot;95&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;95&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;ZSH 플러그인 (Plugins) 설치 방법&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 플러그인을 어떻게 설치하는데?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oh-My-ZSH을 사용한다면, Plugin을 적용하는 것은 매우 간단하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단계는 두 단계를 진행하면 된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1)플러그인 소스 다운로드&lt;/li&gt;
&lt;li&gt;2) .zshrc파일에 플러그인 등록.&lt;/li&gt;
&lt;li&gt;3) 만약 플러그인이 제대로 동작하지 않을 경우, .zshrc 파일에서 수동 실행 (source)하는 방법&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세한 내용은 각 플러그인에서 다시 거론하겠다. 우선 여기서는 큰그림에서 순서 정도로만 생각하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;1) 플러그인 소스코드 다운로드 (Original)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스코드를 브라우저에서 다운로드 받거나, 혹은 &quot;Git clone&quot; 명령어로 git에서 직접 내려 받을 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 플러그인 소스코드 Github ]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AutoSuggestions: &lt;a href=&quot;https://github.com/zsh-users/zsh-autosuggestions&quot;&gt;https://github.com/zsh-users/zsh-autosuggestions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Syntax Hightlighting: &lt;a href=&quot;https://github.com/zsh-users/zsh-syntax-highlighting&quot;&gt;https://github.com/zsh-users/zsh-syntax-highlighting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[ 필자 추천 방법 ]&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;git clone&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://github.com/zsh-users/zsh-autosuggestions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/zsh-users/zsh-autosuggestions&lt;/a&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;git&amp;nbsp;clone&amp;nbsp;&lt;a href=&quot;https://github.com/zsh-users/zsh-syntax-highlighting.git&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/zsh-users/zsh-syntax-highlighting.git&lt;/a&gt;&amp;nbsp;${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;2) .zshrc 파일에 플러그인 등록&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;~/.zshrc 파일을 열어서, 다음과 같이 플러그인을 설정해 준다.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;기본값으로 &quot; plugins=( git ) &quot; 으로 되어 있다. 아래와 같이 본인이 사용할 플러그인 이름 (폴더명)과 동일하게 추가해 주면 된다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1666333138621&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins=(git zsh-autosuggestions zsh-syntax-highlighting)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;plugins 지정은 필수적으로 &quot;source ~/.zshrc&quot; 실행보다 위에 표기되어 있어야 한다.&amp;nbsp;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;전체적인 흐름에 대해서 알아 보았다. 사실 쉽게 문제가 풀린다면, 윗 내용으로만 으로도 플러그인 적용이 될 것이다. 그러나, 때로는 문제가 잘 풀리지 않을 때가 있다. 그렇다면, 아래 각 플러그인 상세 내용을 참조하도록 하자. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;ZSH 자동 완성 (AutoSuggestions)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동완성이라고 소개한 플러그인은, Github에 공개된 플러그인으로, &quot;&lt;b&gt;&lt;a href=&quot;https://github.com/zsh-users/zsh-autosuggestions&quot; data-pjax=&quot;#repo-content-pjax-container&quot; data-turbo-frame=&quot;repo-content-turbo-frame&quot;&gt;zsh-autosuggestions&lt;/a&gt;&quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(출처 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/zsh-users/zsh-autosuggestions&quot;&gt;https://github.com/zsh-users/zsh-autosuggestions&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;동작하는 결과는 다음과 같다. 과거에 실행한 명령이 있다면, 회색으로 아래와 같이 미리 자동완성으로 보여 준다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8iiPv/btrPak9N0KE/9pKh0lkdKE1fE1iLuaLRg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8iiPv/btrPak9N0KE/9pKh0lkdKE1fE1iLuaLRg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8iiPv/btrPak9N0KE/9pKh0lkdKE1fE1iLuaLRg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8iiPv%2FbtrPak9N0KE%2F9pKh0lkdKE1fE1iLuaLRg0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;637&quot; height=&quot;119&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;설치하는 방법은, 위에서 소개한 단계와 같이 두 단계로 이루어져 있다. 이 두단계를 상세하게 살펴보자.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Step 1) Git clone으로 다운로드 받는다. Step 2) .zshrc에 자동으로 실행하도록 rc에 등록해 준다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;1) git 소스 다운로드&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1666268565427&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;2) ~/.zshrc 추가&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;.zshrc 파일을 잘 살표 보면 &quot;plugins= ( git )&quot; 이라고 이미 표기된 곳이 있다. 따라서, 기본적으로는 &quot;추가&quot;가 아니라 &quot;수정&quot;이 되는 것이 정확한 표현이다. 공식 Github에는 다음과 같이 설정하라고 가이드 되어 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1666268627239&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins=( 
    # other plugins...
    zsh-autosuggestions
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 대부분의 경우는 다음과 같이 설정하면 된다. 먼저 &quot;plugins=&quot; 라고 되어 있는 부분을 찾기 바란다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;plugins=(git zsh-autosuggestions)&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; background-color: #9feec3;&quot;&gt;[ 중요 ]&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;중요한점은 .zshrc 파일에서의 &quot;plugins&quot;의 위치이다. 이 위치는 &quot;source ~/.zshrc&quot; 실행라인 보다 위에 위치해야 한다. 대부분 plugins가 동작하지 않는 이유는 이 부분이 잘못 되어 있기 때문이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 위의 plugins가 동작하지 않는다면, ~/.zshrc에서 직접 실행 ( source xxx.sh)가 실행되도록 수동 설정하면 된다. 수동 설정은 아래를 참조하여 진행하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;&lt;b&gt;3) 수동 적용의 경우 (위의 plugins가 동작하지 않는 경우)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;~/.zshrc 마지막 항목에 아래 라인을 추가해 준다.&amp;nbsp; (위의 plugins 항목은 삭제해 준다.)&lt;/p&gt;
&lt;pre id=&quot;code_1666270480750&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;source &amp;lt;autosuggestions의 위치&amp;gt;/zsh-autosuggestions.zsh&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&amp;lt;autosuggestions의 위치&amp;gt;는 github로 다운로드 받은 경로를 적어 준다. 필자의 경우는 아래와 같다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1666270454690&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;source ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;4) ZSH을 다시 시작해 준다.&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널을 다시 시작해 주거나 `source ~/.zshrc`를 실행해 주면 다음과 같이 &quot;자동완성&quot;이 동작하는 것을 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6YhXc/btrPaJhgfH1/EGpX9CHJiM9kW6U2yQFIGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6YhXc/btrPaJhgfH1/EGpX9CHJiM9kW6U2yQFIGK/img.png&quot; data-alt=&quot;ZSH의 자동완성 동작 화면 (Autosuggestions)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6YhXc/btrPaJhgfH1/EGpX9CHJiM9kW6U2yQFIGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6YhXc%2FbtrPaJhgfH1%2FEGpX9CHJiM9kW6U2yQFIGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;637&quot; height=&quot;119&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ZSH의 자동완성 동작 화면 (Autosuggestions)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;하이라이팅 (Syntax Highlighting)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공식 Github : &lt;a href=&quot;https://github.com/zsh-users/zsh-syntax-highlighting&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/zsh-users/zsh-syntax-highlighting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;아래와 같이 github 소스를 다운로드 해준다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1666271701561&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다음으로 다시 위에서 기술한 것과 같이, ~/.zshrc 파일을 열어서, plugins에 &quot;zsh-syntax-highlighting&quot; 을 추가해 준다. 결과적으로, plugins는 아래와 같을 것이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1666271965055&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins=(git zsh-autosuggestions zsh-syntax-highlighting)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 자동완성과 하이라이팅이 실행된 결과의 모습니다.&amp;nbsp; 명령어는 별도로 하이라이팅 된 색상을 보이며, 다음 명령어는 자동완성이 되어 있는 것을 확인할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UmY0J/btrO5eWO1Ym/krxlcOTU1tt7iNPzuQ0FJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UmY0J/btrO5eWO1Ym/krxlcOTU1tt7iNPzuQ0FJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UmY0J/btrO5eWO1Ym/krxlcOTU1tt7iNPzuQ0FJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUmY0J%2FbtrO5eWO1Ym%2FkrxlcOTU1tt7iNPzuQ0FJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;968&quot; height=&quot;221&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/125&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2020.06.01 - [IT 이야기/IT 상식] - [맥북] 맥북 터미널을 이쁘게 - ZSH 초간단 설치와 커스터마이징 (zhs + iTerm2)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;[ 관련 글]&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/211&quot;&gt;2022.11.07 - [IT 이야기] - [Mac OS] 배터리 충전 관리 (limiter) - ft. AlDente&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/210&quot;&gt;2022.11.07 - [IT 이야기/IT 상식] - [맥북 Ventura] 배터리 잔량 퍼센트 보기 - ft. 제어 센터&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/209&quot;&gt;2022.10.31 - [IT 이야기/IT 상식] - [MacOS] 백틱(`) 입력 - 원화(₩)입력 변경 to BQuote(`)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/208&quot;&gt;2022.10.20 - [IT 이야기/IT 상식] - [MacOS - ZSH] 유용한 플러그인 2종 - 자동완성/하이라이트&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/202&quot;&gt;2022.07.25 - [IT 이야기] - [Mac+Chrome] 구글 독스 한글 깨짐 현상 (자/모분리)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/195&quot;&gt;2022.06.29 - [IT 이야기/IT 상식] - [맥북-NTFS] 맥북에서 윈도우 외장하드(NTFS) 쓰기(mount) - 모든버전 사용 가능&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/157&quot;&gt;2021.01.21 - [IT 이야기/IT 상식] - 맥(MacOS)에서 특수문자/한자 입력 하기 -☆ ★ ○ ●&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>AutoSuggesstion</category>
      <category>syntax highlighting</category>
      <category>ZSH Plugin</category>
      <category>ZSH 플러그인</category>
      <category>ZSH 플러그인 수동 설치</category>
      <category>ZSH 플러그인 안됨</category>
      <category>zsh-autosuggestion</category>
      <category>zshrc 플러그인 적용</category>
      <category>자동완성 플러그인</category>
      <category>하이라이팅 플러그인</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/208</guid>
      <comments>https://windflex.tistory.com/208#entry208comment</comments>
      <pubDate>Thu, 20 Oct 2022 22:28:05 +0900</pubDate>
    </item>
    <item>
      <title>[주피터 노트북 커널] jupyter lab/notebook kernel</title>
      <link>https://windflex.tistory.com/207</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;지난번 포스팅에서는 conda를 이용하여 가상환경을 생성/확인/삭제 등에 대하여 알아 보았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;conda 가상환경에 대한 글은 아래 글을 참조 바란다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://richwind.co.kr/206&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.09.19 - [IT 이야기/IT 상식] - [Python 가상환경] conda 설치 및 가상환경 (feat. 내부 로직 &amp;amp; cheat sheet)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cr9jwr/btrMygaNyxb/BbiASv5bdwXweigSri9Irk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cr9jwr/btrMygaNyxb/BbiASv5bdwXweigSri9Irk/img.png&quot; data-alt=&quot;Jupyter lab/ jupyterNotebook Kernel 목록에 가상환경이 표기되지 않는다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cr9jwr/btrMygaNyxb/BbiASv5bdwXweigSri9Irk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcr9jwr%2FbtrMygaNyxb%2FBbiASv5bdwXweigSri9Irk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;345&quot; height=&quot;188&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Jupyter lab/ jupyterNotebook Kernel 목록에 가상환경이 표기되지 않는다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그런데, conda에서 가상환경을 생성하였다고 하더라도, Jupyter Lab 또는 Jupyter Notebook에서는 신규 생성한 가상환경으로 시작할 수가 없다. 물론, 가상환경으로 변경(conda activate) 후에 jupyter Lab 서비스 구동 자체 다시 시작하면 해당 가상환경으로 Jupyter를 사용할 수 있기는 하다. 그러나, 매번 Jupyter 서비스를 다시 재구동 할수는 없지 않겠는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;conda (Anaconda)와 Jupyter가 동일 제품이라면 자동으로 연동 되겠지만, 서로 다른 제품/솔루션이므로 아쉽게도 서로 자동 연동이 되지 않는다. 다행 스럽게도 Jupyter Lab/Notebook에서는 이렇게 생성한 가상환경을 Kernel로 등록할 수 있도록 하는 기능이 마련되어 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Jupyter Kernel 등록&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[ ipykernel 방법 ]&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1663593791716&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ pip install ipykernel
$ python -m ipykernel install --user --name &amp;lt;가상환경 이름&amp;gt; --display-name &amp;lt;표기할 커널 이름&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxTHwh/btrMyifsro9/vismlbGF6hzbTYfAmthhq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxTHwh/btrMyifsro9/vismlbGF6hzbTYfAmthhq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxTHwh/btrMyifsro9/vismlbGF6hzbTYfAmthhq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxTHwh%2FbtrMyifsro9%2FvismlbGF6hzbTYfAmthhq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;749&quot; height=&quot;119&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 `ipython kernel`을 사용하는 방법들도 있다. 그러나, 이 경우에는 가상환경과 제대로 매핑되지 않는 경우가 많다. 안정적인 ipykernel을 사용하도록 하자.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1663596037991&quot; class=&quot;brainfuck&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;jupyter kernelspec 

ipython kernel install --user --name &amp;lt;가상환경 이름&amp;gt; --display-name &amp;lt;표시할 커널이름&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Jupyter Kernel 삭제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1663593710772&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ jupyter kernelspec remove &amp;lt;삭제할 커널 이름&amp;gt;
ex) jupyter kernelspec remove ML3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;내부 로직 (상세)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Jupyter 내부로직을 한번 살펴 보면 (소스까지 보지는 않았지만),&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;`&amp;lt;home dir&amp;gt;/.local/share/`로 이동해 보면, Jupyter 디렉토리가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;하위 폴더에는 우리가 궁금해하는 &quot;kernels&quot; 디렉토리가 있으며, 다시 그 하위 디렉토리가 바로 우리가 등록하고자 하는 jupyter kernel의 이름들 이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9zUw7/btrMwZVc9pl/vuMn8905THMN0CONXB1HfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9zUw7/btrMwZVc9pl/vuMn8905THMN0CONXB1HfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9zUw7/btrMwZVc9pl/vuMn8905THMN0CONXB1HfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9zUw7%2FbtrMwZVc9pl%2FvuMn8905THMN0CONXB1HfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;690&quot; height=&quot;135&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;kernel이름의 디렉토리에는 &quot;kernel.json&quot;이라는 설정 파일이 있는데, 여기서 중요한 부분은 어떤 가상환경을 사용하고 있는지를 지정하고 있다. 이렇게 우리가 생성한 가상환경과, Jupyter가 그 가상환경을 사용하게 되는지 내부 로직을 짐작해 볼 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbBK1L/btrMy0S9bQh/VhKmirf5eNg3HzarcGoyD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbBK1L/btrMy0S9bQh/VhKmirf5eNg3HzarcGoyD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbBK1L/btrMy0S9bQh/VhKmirf5eNg3HzarcGoyD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbBK1L%2FbtrMy0S9bQh%2FVhKmirf5eNg3HzarcGoyD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;866&quot; height=&quot;317&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이런 부분을 알게 되었다면, 우리는 수동으로 Jupyter Kernel을 등록해 볼 수 있을 것이다.&amp;nbsp; 결국은 jupyter kernel이 이해할 수 있는 파일/디렉토리 구조를 생성하고, kernel.json을 형태와 설정 정보에 맞게 파일쓰기를 해주는 과정이라고 볼 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;굳이 수동 등록하지는 않을 것이다. (우리의 시간은 소중하니까.)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ipykernel과 kernelspec 들이 어떤 역할을 해 주는지만 파악하고 넘어가도록 하자.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[관련 글]&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Conda-Jupyter] Conda 가상환경과 Jupyter Kernel 연동/생성/삭제&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Jupyter Kernel 추가] conda 가상환경을 jupyter Kernel로 추가하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/207&quot;&gt;2022.09.19 - [개발 이야기/Python] - [주피터노트북 커널] jupyter lab/notebook kernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/126&quot;&gt;2020.06.04 - [개발 이야기/Python] - [파이썬] Anaconda x Jupyter notebook 설치 및 설정 방법 - 가상환경으로 파이썬 개발환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/19&quot;&gt;2020.03.10 - [IT 이야기] - Python x Jupyter Notebook 설치 및 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/206&quot;&gt;2022.09.19 - [IT 이야기/IT 상식] - [Python 가상환경] conda 설치 및 가상환경 (feat. 내부 로직 &amp;amp; cheat sheet)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 이야기/Python</category>
      <category>ipykernel</category>
      <category>jupyter kernel 등록</category>
      <category>jupyter kernel 목록</category>
      <category>jupyter kernel 삭제</category>
      <category>Jupyter Kernel 설정</category>
      <category>jupyter kernelspec</category>
      <category>jupyter notebook kernel</category>
      <category>kernel install</category>
      <category>kernel.json</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/207</guid>
      <comments>https://windflex.tistory.com/207#entry207comment</comments>
      <pubDate>Mon, 19 Sep 2022 23:06:20 +0900</pubDate>
    </item>
    <item>
      <title>[Python 가상환경] conda 설치 및 가상환경 (feat. 내부 로직 &amp;amp; cheat sheet)</title>
      <link>https://windflex.tistory.com/206</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q8WD0/btrMwZucqVa/E5V679bVbdFDKeNnWRYYO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q8WD0/btrMwZucqVa/E5V679bVbdFDKeNnWRYYO1/img.png&quot; data-alt=&quot;anaconda 가상환경에 대해서 알아보자. 원리도 함께.. conda create, conda remove, conda env list&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q8WD0/btrMwZucqVa/E5V679bVbdFDKeNnWRYYO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq8WD0%2FbtrMwZucqVa%2FE5V679bVbdFDKeNnWRYYO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;514&quot; height=&quot;249&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;anaconda 가상환경에 대해서 알아보자. 원리도 함께.. conda create, conda remove, conda env list&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Python을 사용하는 User들에게 ananconda (conda)는 매우 익숙한 패키지 관리자이다. 그러나, 익힐것이 많은 우리는 매번 conda 명령어가 가물가물하다. 또한, pip 명령어와, 명령어간 순서가 종종 혼동되기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;env 인가? envs 인가?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오늘날, 이런 명령어 하나 하나를 모두 기억하고 살기에는 우리가 기억하고 있어야 할것이 너무 많다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;또한, 종종 내부 로직을 이해하면 외우지 않아도 자연스럽게 암기가 되기도 한다. 내부 로직/원리를 함께 살펴 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;conda : 패키지 설치 / 버전&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;conda에서 가장 자주 사용하는 것은 당연히 패키지 설치 일것이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1663587841524&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda install &amp;lt;package name1&amp;gt; &amp;lt;package name2&amp;gt; ...
ex)
$ conda install numpy pandas&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;345&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cU4ERJ/btrMzEoH2CB/rvCsgHKuGK3AasSC4wTPUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cU4ERJ/btrMzEoH2CB/rvCsgHKuGK3AasSC4wTPUk/img.png&quot; data-alt=&quot;conda install 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cU4ERJ/btrMzEoH2CB/rvCsgHKuGK3AasSC4wTPUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcU4ERJ%2FbtrMzEoH2CB%2FrvCsgHKuGK3AasSC4wTPUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;628&quot; height=&quot;266&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;345&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;conda install 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 설치한 버전의 업데이트는 `update` 명령어를 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1663588089863&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda update pandas&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;[참조] 경우에 따라서는, `PackageNotInstalledError: Package is not installed in prefix.` 라는 에러가 발생하기도 한다. `conda list`를 실행하면 패키지가 설치되어 있는데, `update`에서 패키지를 인식을 못한다. 이것은 `pip`명령어로 설치한 패키지에서 발생한다. `conda install`로 설치한 패키지의 경우는 발생하지 않는다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;가상환경 생성 : conda create&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python을 사용하면서, 다양한 Applicaiton을 개발하다보면 Python 버전 디펜던시, 패키지 버전관리 등을 필요로 하게 된다. 특히, ML 프로젝트를 하게 되면, Cuda/CuDNN과 python 버전에 따라서 구동 여부가 달라지기도 한다. 또한 Tensorflow/Pytorch가 동시에 설치되어 있는 경우 충돌이 나기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1663588939455&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda create --name ML python=3.9
or
$ conda create -n ML python=3.9&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;[형태] conda create --name &amp;lt;가상환경 표시 이름&amp;gt; python=&amp;lt;버전&amp;gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;매번 Python과 패키지를 다르게 설치할 수 없기 때문에, 가상환경을 사용하여 서로 독립적인 환경을 세팅해 준다. (좀 더 자세히 들여다 보면, Docker/Container의 전신과 유사한 형태로 동작하는 것을 알수 있다. Python 실행 파일을 특정 하위 디렉토리에 복사하고, root directory를 변경해 주는 형태를 사용한다. )&lt;br /&gt;즉, `conda create` 과정은 특정 directory를 생성하고 버전에 맞는 python bin와 pip 등 기본 파일을 복사/설치하는 과정이다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;이러한 과정을 이해하면 당연하게 내부 로직을 이해할 수 있는데, 기본적으로 가상환경(venv)마다 디렉토리가 정해져 있는 것을 알수 있다. 아래에서 거론될 Activate/Deactivate과정은 `change root dir` 과정이라고 볼 수 있다. 또한 신규로 설치되는 패키지들은 변경된 root dir 아래 새롭게 다시 설치되는 것이다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;* docker의 전신인 Linux container 에서는 `chroot`를 활용하여 기준이 되는 root dir을 변경하였다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성된 가상환경 리스트 확인&lt;/p&gt;
&lt;pre id=&quot;code_1663589174072&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda env list&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Djx0n/btrMw6UiGZx/GlXILqCrdmApGbjqeVaMx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Djx0n/btrMw6UiGZx/GlXILqCrdmApGbjqeVaMx0/img.png&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;179&quot; data-is-animation=&quot;false&quot; style=&quot;width: 52.8947%; margin-right: 10px;&quot; data-widthpercent=&quot;53.52&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Djx0n/btrMw6UiGZx/GlXILqCrdmApGbjqeVaMx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDjx0n%2FbtrMw6UiGZx%2FGlXILqCrdmApGbjqeVaMx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;711&quot; height=&quot;179&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OPFEn/btrMwZOqqcw/Kpvst4yYKpupSioZZxFBKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OPFEn/btrMwZOqqcw/Kpvst4yYKpupSioZZxFBKk/img.png&quot; data-origin-width=&quot;759&quot; data-origin-height=&quot;220&quot; data-is-animation=&quot;false&quot; style=&quot;width: 45.9425%;&quot; data-widthpercent=&quot;46.48&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OPFEn/btrMwZOqqcw/Kpvst4yYKpupSioZZxFBKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOPFEn%2FbtrMwZOqqcw%2FKpvst4yYKpupSioZZxFBKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;759&quot; height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;conda env list 명령어를 사용하면 생성된 가상환경을 확인 할 수 있다. `conda env list` 명령어는 사실상 `ls ~/ananconda3/envs`와 동일한 역할을 한다고 생각할 수 있다.&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`conda env list`를 실행하면 가상환경 리스트를 확인할 수 있는데, 설치된 가상 환경의 directory 위치를 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eb9s9F/btrMxCrRte1/KuYcXjRwz57KGrh5huvb7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eb9s9F/btrMxCrRte1/KuYcXjRwz57KGrh5huvb7K/img.png&quot; data-alt=&quot;각 가상환경의 home 디렉터리에 가보면, python 자체가 모두 복제가 되어 있는 것을 알수 있다. bin/에는 python3등 실행 바이너리가 위치해 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eb9s9F/btrMxCrRte1/KuYcXjRwz57KGrh5huvb7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feb9s9F%2FbtrMxCrRte1%2FKuYcXjRwz57KGrh5huvb7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;861&quot; height=&quot;63&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;각 가상환경의 home 디렉터리에 가보면, python 자체가 모두 복제가 되어 있는 것을 알수 있다. bin/에는 python3등 실행 바이너리가 위치해 있다.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, bin/외에 별도로 설치한 개별 패키지들은 어디에 위치해 있는 것일까?&amp;nbsp; 가상환경의 rootdir 아래를 잘 살펴보면, lib/python3.x 위치를 살펴보자. 아래와 같이 `conda install` 로 설치된 패키지들이 .py 또는 라이브러리 형태로 저장되어 있다.&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMfBhm/btrMzD4pIRL/wKTbkV4JeT6sKJouupk1gK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMfBhm/btrMzD4pIRL/wKTbkV4JeT6sKJouupk1gK/img.png&quot; data-alt=&quot;~/anaconda3/envs/ML3/lib/python3.9 하위에 개별 설치한 패키지들이 저장되어 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMfBhm/btrMzD4pIRL/wKTbkV4JeT6sKJouupk1gK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMfBhm%2FbtrMzD4pIRL%2FwKTbkV4JeT6sKJouupk1gK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;734&quot; height=&quot;358&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;~/anaconda3/envs/ML3/lib/python3.9 하위에 개별 설치한 패키지들이 저장되어 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;가상환경 활성화/비활성화 (Activate/Deactivate)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1663590235872&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 가상환경 활성화 -&amp;gt; 지정한 환경으로 root dir 변경
$ conda activate &amp;lt;가상환경 이름&amp;gt;
ex) $ conda activate ML3

# 가상환경 비활성화 -&amp;gt; 이전 환경으로 root dir 변경
$ conda deactivate&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;activate / deactivate가 어떤 역할을 하는지 살펴보기 위해서, 가상환경에 진입하여 각각 환경변수를 비교하여 보자. `$echo PATH`를 실행해 보면, 가상환경 rootdir아래 `bin/`와 `condabin/`가 최우선순위 경로로 변경되어 있는 것을 알 수 있다. 이것은 python 명령어를 실행하거나, python package를 실행할 경우 가상환경에서 먼저 찾아보라는 의미를 갖는다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;/home/xxxx/anaconda3/bin:/home/xxxxx/anaconda3/condabin:/home/xxxxxx/.pyenv/shims:&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;[ ML3 가상환경 진입후 ]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1663591041447&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(ML3) data:~/anaconda3$ echo $PATH
//src/google-cloud-sdk/bin:/home//anaconda3/envs/ML3/bin:/home//anaconda3/condabin:/home//.pyenv/shims:/home//.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;[ ML3 가상환경 비활성화 후 ]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1663591069348&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//src/google-cloud-sdk/bin:/home//anaconda3/bin:/home//anaconda3/condabin:/home//.pyenv/shims:/home//.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;가상환경 삭제 - conda remove&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 살펴본 가상환경 생성/동작원리를 이해하면, 여러가지를 자동적으로 파악 할 수 있다. 대표적으로 가상환경이 늘어나게 되면, 동일 PC/서버 환경에서는 그만큼의 Python Bin와 Package의 모든 파일이 `가상환경 개수`만큼 복제되어 있다고 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 불필요한 가상환경을 삭제가 필요하기도 하다. 가상환경을 삭제하려면, conda의 `remove` 명령어를 사용하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1663591451096&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ conda env remove -n &amp;lt;가상환경 이름&amp;gt;
ex) conda env remove -n ML3&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;당연하게도, 삭제하는 과정은 &amp;lt;anaconda home&amp;gt;/envs 아래에서 &amp;lt;가상환경 이름&amp;gt;에 해당하는 directory 자체를 삭제해 버리는 과정이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;b&gt;Conda Cheat Sheet&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 conda 공식 홈에서 제공하고 있는 conda cheat sheet이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cl5XOn/btrMyiT13nU/xBNDzSMkz7K5rRmNpy3v4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cl5XOn/btrMyiT13nU/xBNDzSMkz7K5rRmNpy3v4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cl5XOn/btrMyiT13nU/xBNDzSMkz7K5rRmNpy3v4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcl5XOn%2FbtrMyiT13nU%2FxBNDzSMkz7K5rRmNpy3v4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;825&quot; height=&quot;312&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;626&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deEHsl/btrMxVrfKyl/ebK5PsWWw2aM2vqayt4q0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deEHsl/btrMxVrfKyl/ebK5PsWWw2aM2vqayt4q0K/img.png&quot; data-alt=&quot;출처 : conda 공식 홈페이지 (https://docs.conda.io/projects/conda/en/4.6.0/_downloads/52a95608c49671267e40c689e0bc00ca/conda-cheatsheet.pdf)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deEHsl/btrMxVrfKyl/ebK5PsWWw2aM2vqayt4q0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeEHsl%2FbtrMxVrfKyl%2FebK5PsWWw2aM2vqayt4q0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;978&quot; height=&quot;626&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;626&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : conda 공식 홈페이지 (https://docs.conda.io/projects/conda/en/4.6.0/_downloads/52a95608c49671267e40c689e0bc00ca/conda-cheatsheet.pdf)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[관련 글]&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Conda-Jupyter] Conda 가상환경과 Jupyter Kernel 연동/생성/삭제&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Jupyter Kernel 추가] conda 가상환경을 jupyter Kernel로 추가하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/207&quot;&gt;2022.09.19 - [개발 이야기/Python] - [주피터노트북 커널] jupyter lab/notebook kernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/126&quot;&gt;2020.06.04 - [개발 이야기/Python] - [파이썬] Anaconda x Jupyter notebook 설치 및 설정 방법 - 가상환경으로 파이썬 개발환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/19&quot;&gt;2020.03.10 - [IT 이야기] - Python x Jupyter Notebook 설치 및 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/206&quot;&gt;2022.09.19 - [IT 이야기/IT 상식] - [Python 가상환경] conda 설치 및 가상환경 (feat. 내부 로직 &amp;amp; cheat sheet)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>Anaconda</category>
      <category>conda</category>
      <category>conda create</category>
      <category>conda env</category>
      <category>conda install</category>
      <category>conda list</category>
      <category>conda remove</category>
      <category>가상환경 삭제</category>
      <category>아나콘다 가상환경</category>
      <category>파이썬 가상환경 생성</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/206</guid>
      <comments>https://windflex.tistory.com/206#entry206comment</comments>
      <pubDate>Mon, 19 Sep 2022 21:54:52 +0900</pubDate>
    </item>
    <item>
      <title>[App] Android compileSdkVersion Error (ft. API 버전)</title>
      <link>https://windflex.tistory.com/205</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;179&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0jcVX/btrL3y4c1AB/M206610OP2A04YNPULqqk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0jcVX/btrL3y4c1AB/M206610OP2A04YNPULqqk1/img.png&quot; data-alt=&quot;안드로이드 스튜디오 컴파일 에러&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0jcVX/btrL3y4c1AB/M206610OP2A04YNPULqqk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0jcVX%2FbtrL3y4c1AB%2FM206610OP2A04YNPULqqk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;282&quot; height=&quot;179&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;179&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;안드로이드 스튜디오 컴파일 에러&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;컴파일 에러 : 개발자에게 가장 싫어하는 에러&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;안드로이드 앱 개발 혹은 Cross Platform App 개발하면서, 아래와 같은 &quot;CompileSdkVersion Error&quot;를 종종 만나게 된다. 특히, 프로젝트 세팅을 처음부터 시작한 것이 아니라, Template 또는 Skeleton Project로 부터 시작하는 경우에서 발생이 빈번하다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Your project requires a higher compileSdkVersion. ㅜ_ㅜ&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이런 컴파일류의 에러가 발생하면 처음에는 매우 당혹스럽기만 하다. 왜냐하면, 아직 아무것도 하지 않았기 때문이다. 아직 시작도 않해봤는데, 바로 컴파일 에러부터 발생하면, 환경 세팅 문제인데 이런류의 에러는 한번 꼬이면 잡아내기가 무척 까다롭기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다행이 이번 CompileSdkVersion Error는 어려운 부분이 아니긴 하다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1686&quot; data-origin-height=&quot;926&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bi4erL/btrL1yXNxtH/ee0Q3ooCG61Dn5dKSghWFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bi4erL/btrL1yXNxtH/ee0Q3ooCG61Dn5dKSghWFK/img.png&quot; data-alt=&quot;Android Studio. compileSdkVersion Error. Build Failed 이 발생한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bi4erL/btrL1yXNxtH/ee0Q3ooCG61Dn5dKSghWFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbi4erL%2FbtrL1yXNxtH%2Fee0Q3ooCG61Dn5dKSghWFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1686&quot; height=&quot;926&quot; data-origin-width=&quot;1686&quot; data-origin-height=&quot;926&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Android Studio. compileSdkVersion Error. Build Failed 이 발생한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;해결 방안&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;에러의 내용을 자세히 살펴 보면, 이런 에러의 경우, Java Native를 컴파일 해야 하는데 compile Version이 필요한 SDK 버전 보다 낮다는 것이 문제이다. 원인 파악은 되었고, 그렇다면 SDK 버전을 올려주면 될것 이다. 여기서 2가지 작업이 필요하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;1) 실제 상위버전의 SDK를 설치해 주는것 --&amp;gt; &lt;span style=&quot;background-color: #f89009;&quot;&gt;SDK Manager&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;2) 상위버전의 SDK를 사용할 수 있다고 표기 해 주는 것 --&amp;gt; &lt;span style=&quot;background-color: #f89009;&quot;&gt;build.gradle&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;SDK Manager&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Android Studio의 메뉴중, SDK Manager를 열어주자. Android Studio의 버전에 따라 다르지만, &lt;u&gt;최상단 메뉴 &amp;gt; Tools &amp;gt; SDK Manager&lt;/u&gt; 메뉴에서 찾을 수 있다. 이번 에러의 경우, API 31 이상을 요구하고 있기 때문에 31 또는 그 상위의 버전을 추가 설치해 주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GCGgk/btrL33WZZOK/rLHjucH2mFhkDuIKIibblk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GCGgk/btrL33WZZOK/rLHjucH2mFhkDuIKIibblk/img.png&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;900&quot; data-is-animation=&quot;false&quot; style=&quot;width: 29.6754%; margin-right: 10px;&quot; data-widthpercent=&quot;30.02&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GCGgk/btrL33WZZOK/rLHjucH2mFhkDuIKIibblk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGCGgk%2FbtrL33WZZOK%2FrLHjucH2mFhkDuIKIibblk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;568&quot; height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcHJJ3/btrLVYwk1ls/hQl2UVRfps2OkRqkqAo4v0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcHJJ3/btrLVYwk1ls/hQl2UVRfps2OkRqkqAo4v0/img.png&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;824&quot; data-is-animation=&quot;false&quot; style=&quot;width: 69.1618%;&quot; data-widthpercent=&quot;69.98&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcHJJ3/btrLVYwk1ls/hQl2UVRfps2OkRqkqAo4v0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcHJJ3%2FbtrLVYwk1ls%2FhQl2UVRfps2OkRqkqAo4v0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1212&quot; height=&quot;824&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Android Studio SDK Manager. Android SDK API 31 이상을 필요로 하고 있다.&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;android/app/build.gradle&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 31만 설치해 주면 끝날 줄 알았는데, Android를 Compile할 때 설계도와 같은 Builld.gradle에서 API 최저~최상에 대한 정의가 되어 있다. 여기에서 요구되는 구동 환경 보다 API 버전 설정이 절적하지 않으면, 위와 같은 에러가 발생하게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은, &quot;android/app/build.gradle&quot; 경로 위치에 주의하길 바란다.&amp;nbsp; 동일 이름의 build.gradle은 &quot;android/build.gradle&quot;이 또 하나 존재한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;android/app/build.gradle의 하단쯤에 compileSdkVersion xx 의 버전을 요구하는 레벨 혹은 그 이상으로 수정해 주자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by2bM3/btrL2ogsana/O2lHWwjBwJtwkqLjPv54bK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by2bM3/btrL2ogsana/O2lHWwjBwJtwkqLjPv54bK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by2bM3/btrL2ogsana/O2lHWwjBwJtwkqLjPv54bK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby2bM3%2FbtrL2ogsana%2FO2lHWwjBwJtwkqLjPv54bK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1212&quot; height=&quot;824&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;824&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정에 따라서는 하단에 존재하는, defaultConfig 항목에 minSdkVersion, targetSdkVersion 도 조정해 주길 바란다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다시 컴파일을 진행하면, 정상 동작함을 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>Android Studio Compile Error</category>
      <category>android/app/build.gradle</category>
      <category>build.gradle</category>
      <category>compile Version SDK</category>
      <category>compileSdk Version Error</category>
      <category>higher compileSdkVersion</category>
      <category>targetSdkVersion</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/205</guid>
      <comments>https://windflex.tistory.com/205#entry205comment</comments>
      <pubDate>Tue, 13 Sep 2022 15:41:22 +0900</pubDate>
    </item>
    <item>
      <title>[텐서플로우 - TFIO] 텐서플로우 io 에러 (NotImplementedError)</title>
      <link>https://windflex.tistory.com/204</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p6aZR/btrLvKw7zeq/JzKcjYvvvq0g6jSDeH4ak1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p6aZR/btrLvKw7zeq/JzKcjYvvvq0g6jSDeH4ak1/img.png&quot; data-alt=&quot;Tensorflow IO NotImplementedError : unable to open&amp;amp;amp;nbsp;libtensorflow_io.so&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p6aZR/btrLvKw7zeq/JzKcjYvvvq0g6jSDeH4ak1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp6aZR%2FbtrLvKw7zeq%2FJzKcjYvvvq0g6jSDeH4ak1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;339&quot; height=&quot;339&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Tensorflow IO NotImplementedError : unable to open&amp;amp;nbsp;libtensorflow_io.so&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Tensorflow IO (TFIO)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Tensorflow_io는 GPU를 사용하여 파일 로드, 디코딩, 전처리 등을 빠르게 할 수 있어서 매우 유용한 툴이다. 필자 또한 다수의 파일을 읽고 전처리할 때 사용하고 있다. 처음에는, 각 파일별로 전처리한 결과를 저장해 놓고 그때 그때 저장해둔 전처리 결과물을 로딩하여 사용했으나, Tensorflow_io를 사용한 이후 부터는 실행하는 Runtime 시점에 파일로딩-&amp;gt;전처리까지 실시간으로 처리하여도 속도 측면에서 뛰어남을 체감하고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;더욱이, 전처리하는 과정에서 일부 수정이 발생하면, 미리 저장해둔 전처리 결과물을 재 생성해야 한다. 이 때문에, 전처리 과정에서 파라미터 변경 등에 따른 실험이 필요하다면 필수적으로 Tensorflow_io를 사용하게 될 것 이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그런데,&lt;br /&gt;Tensorflow_io를 실행하자 마자 에러가 발생하는 경우가 있다.&amp;nbsp;&lt;br /&gt;보통 tensorflow_io의 Audio 모듈을 사용할 경우이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1337&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btpdDm/btrLuBOdvhW/wINaHzVQxUNBvRoVRko7t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btpdDm/btrLuBOdvhW/wINaHzVQxUNBvRoVRko7t0/img.png&quot; data-alt=&quot;Tensorflow_io NotimplementedError&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btpdDm/btrLuBOdvhW/wINaHzVQxUNBvRoVRko7t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtpdDm%2FbtrLuBOdvhW%2FwINaHzVQxUNBvRoVRko7t0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1337&quot; height=&quot;341&quot; data-origin-width=&quot;1337&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Tensorflow_io NotimplementedError&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;문제의 원인&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아래와 같이 NotImplementedError가 발생하기도 한다. 특히 Tensorflow 최신버전을 사용하는 경우, 이러한 현상이 더욱 빈번하게 발생하는 듯 하다. 구글링을 통하여 검색해 보면, Conda repository에서 아직 지원을 하지 않는다는 등의 이야기가 있는데, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;거두 절미하고 필자가 얻은 답은 &quot;버전 문제&quot; 때문이다.&lt;/span&gt; 버전 미스매칭 때문에 발생하는 일인데, 최근 Tesnorflow_io에서 라이브러리의 경로 등이 변경된것이 아닌가 추정하고 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1662427135255&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NotImplementedError: in user code:
   (중략) 
    File &quot;/home/svcapp/.local/lib/python3.9/site-packages/tensorflow_io/python/ops/__init__.py&quot;, line 69, in _load_library
        raise NotImplementedError(

    NotImplementedError: unable to open file: libtensorflow_io.so, from paths: ['/home/svcapp/.local/lib/python3.9/site-packages/tensorflow_io/python/ops/libtensorflow_io.so']
    caused by: ['/home/svcapp/.local/lib/python3.9/site-packages/tensorflow_io/python/ops/libtensorflow_io.so: undefined symbol: _ZNK10tensorflow4data11DatasetBase8FinalizeEPNS_15OpKernelContextESt8functionIFNS_8StatusOrISt10unique_ptrIS1_NS_4core15RefCountDeleterEEEEvEE']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;해결 방안&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;여러가지 시도를 해 보았으나, 필자가 해결한 방법은 특정 버전으로 다시 설치하는 방법이다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;필자는 아래와 같이 기존 tensorflow_io를 삭제하고 0.23.1 버전으로 재설치한 후 문제가 해결 되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1662427287527&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;!pip uninstall tensorflow_io -y
!pip install tensorflow_io==0.23.1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;참고적으로, 구글링의 결과로 아래와 같이 &quot;--no-deps&quot; 옵션으로 재설치하라는 가이드도 존재하였으나, 필자의 경우 문제가 해결 되지 않았다. 경우에 따라서는 도움이 될 수 있으나, 추가로 첨부하고자 한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1662427519228&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip uninstall tensorflow
pip uninstall tensorflow-io
pip install tensorflow-gpu
pip install --no-deps tensorflow-io&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>머신러닝 이야기</category>
      <category>libtensorflow_io.so</category>
      <category>tensorflow io NotImplemented Error</category>
      <category>tensorflow-io 에러</category>
      <category>tensorflow_io</category>
      <category>tensorflow_io==0.23.1</category>
      <category>tfio</category>
      <category>tfio Error</category>
      <category>unable to open libtensorflow_io.so</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/204</guid>
      <comments>https://windflex.tistory.com/204#entry204comment</comments>
      <pubDate>Tue, 6 Sep 2022 10:35:10 +0900</pubDate>
    </item>
    <item>
      <title>산업안전보건교육  2022년 3분기 비사무직</title>
      <link>https://windflex.tistory.com/203</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;산업안전보건교육&amp;nbsp; 2022년 3분기 비사무직&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ogMAx/btrKzEL8Hxo/1k4iAvg1gVkk1kily9Xtdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ogMAx/btrKzEL8Hxo/1k4iAvg1gVkk1kily9Xtdk/img.png&quot; data-alt=&quot;산업안전보건교육 2022&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ogMAx/btrKzEL8Hxo/1k4iAvg1gVkk1kily9Xtdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FogMAx%2FbtrKzEL8Hxo%2F1k4iAvg1gVkk1kily9Xtdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;473&quot; height=&quot;401&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;산업안전보건교육 2022&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232;&quot;&gt;1 [O/X 문제] 저는 조리사로 매일 조리용 장화와 장갑을 사용하고 있습니다. 가끔 일반 장화를 사용할 때가 있는데 이것도 위험성 평가 시 유해∙위험요인 항목에 포함될까요?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. O&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. X&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;1번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;조리실은 특히 물기와 기름기가 많기 때문에 미끄럼방지 장화를 신어야 합니다. 이외에도 위험성평가에서는 조리용 장갑, 조명등 간격, 코드 위치 등을 점검합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;2 다음 중 위험성평가의 특징으로 올바른 것은 무엇인가?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 체계적으로 문서화하고 지속적으로 수정 &amp;middot; 보완하며 조직적 &amp;middot; 과학적인 방법으로 진행된다는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 감각적 또는 경험적으로 &amp;lsquo;이것은 위험하다&amp;rsquo; 고 판단한 것 만을 평가대상으로 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 유해&amp;middot;위험 요인을 일부만 찾아내면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 표면적으로 드러난 위험∙위해 요인을 찾는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;1번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;위험성평가는 체계적으로 문서화하고 지속적으로 수정 &amp;middot; 보완하며 조직적 &amp;middot; 과학적인 방법으로 진행된다는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;3 다음은 직무스트레스에 의한 건강장해를 설명한 것이다. 빈 칸에 알맞은 답을 쓰시오.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;□□□이란 한 가지 일에 몰두하다 신체적, 정신적으로 모든 에너지가 소진된 상태를 의미합니다. 최근 세계보건기구는.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;□□□증후군을 질환은 아니지만 성공적으로 관리되지 않는 만성적 직장 스트레스로 인한 증후군으로 정의했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3&lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;/100&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;번 아웃,번아웃&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;4 [O/X 문제] 공기감염은 비말감염보다 전파력이 약하다.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. O&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. X&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;2번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;공기감염은 비말에서 수분이 다 기화하고 병원체 등이 남은 비말핵이 공기 중에서 부유하다가 사람에게 흡입되어 발생하는 것으로 비말핵의 지름이 5㎛보다 작아 최대 약 50m까지 퍼질 수 있습니다. 따라서 공기감염을 일으키는 질병은 대규모 감염을 발생시키기 때문에 특히 유의해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;5&amp;nbsp; 다음은 스트레스의 반응 중 어떤 것을 설명한 것인가?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&quot;우유부단, 혼란, 우울, 불안, 신경과민, 분노 등의 반응으로 나타나며 만성 스트레스가 지속되면 감정적 손상이 지속되고 과민하게 되며, 수면 패턴에도 영향을 주게 됩니다.&quot; (5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 생리적 반응&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 감정적 반응&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 인지적 반응&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 행동적 반응&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;2번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;스트레스 상황에 대한 개인의 반응은 상황을 어떻게 생각하고, 기대하며 평가하느냐는 인지과정에 의해 큰 영향을 받는다고 볼 수 있습니다. 스트레스에 의한 반응으로는 생리적 반응, 감정적 반응, 인지적 반응, 행동적 반응이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;6 다음 중 위험성평가에 대한 설명으로 옳지 않은 것은 무엇인가?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 사업주가 사업장의 유해 &amp;middot; 위험 요인을 파악하고 해당 유해 &amp;middot; 위험 요인에 의한 부상 또는 질병의 발생 가능성과 중대성을 추정, 결정해 감소 대책을 수립하고 실행하는 일련의 과정을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 위험성평가의 실시 목적은 사고 후 재발을 방지하지 위한 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 사업주의 자율적인 재해 예방 활동을 강화하기 위해 2010년부터 3년 동안 위험성평가 시범사업을 실시하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 2013년부터 국내 전 사업장을 대상으로 위험성평가 제도를 본격 시행하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;2번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;위험성평가의 실시 목적은 사고를 미연에 방지하는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;7 다음중 산업안전보건관리비 대상액에 대한 설명으로 옳지 않은 것은 무엇인가?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 산업안전보건관리비 산정의 기초가 되는 금액&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 공사내역의 구분 여부에 따라 대상액을 산정해야 함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 공사내역의 구분여부와 관계없이 정액으로 산정함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 공사내역이 구분되어 있는 경우, 재료비 + 직접노무비&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 공사내역이 구분되지 않은 경우, 총공사금액의 70%&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;3번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;대상액은 산업안전보건관리비 산정의 기초가 되는 금액으로 공사원가계산서에서 재료비와 직접 노무비를 합한 금액을 말합니다. 여기에서 재료비로는 발주자가 재료를 제공할 경우 해당 재료비 또는 완제품의 가액을 포함한 금액이 해당됩니다. 대상액을 산정할 때는 공사내역이 구분되어 있는 경우와 구분되어 있지 않은 경우로 구분하여 산정해야 합니다. 산업안전보건관리비 계상 시 대상액이 구분되지 않은 공사에 있어서는 총 공사금액의 70%에 해당하는 금액을 대상액으로 보는데요. 그 이유는 재료비와 직접노무비를 합한 금액이 통상적으로 총 공사금액의 70% 정도에 해당하기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;8 [O/X 문제] 산업안전보건관리비는 「전기공사업법」에 따른 전기공사로서 저압 &amp;middot; 고압 또는 특별고압 작업으로 이루어지는 공사와「정보통신공사업법」 따른 정보통신공사 중단가계약에 의해 행해지는 공사에 대해서는 총 계약금액을 기준으로 적용한다.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. O&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. X&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;1번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;산업안전보건관리비는 「산업재해보상보험법」의 적용을 받는 공사 중 총 공사금액이 2천만 원 이상인 공사에 한해 적용이 가능합니다. 다만,「전기공사업법」에 따른 전기공사로서 저압 &amp;middot; 고압 또는 특별고압 작업으로 이루어지는 공사와「정보통신공사업법」 따른 정보통신공사 중단가계약에 의해 행해지는 공사에 대해서는 총 계약금액을 기준으로 적용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;9 [O/X 문제] 스트레스는 모든 병의 근원이므로 무조건 제거하거나 줄여야 한다.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. O&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. X&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;2번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;적절한 스트레스는 삶의 활력이 되고 도전을 하게 되는 힘이 되기도 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;10 다음은 무엇에 대한 설명인가? 빈 칸에 알맞은 답을 쓰시오.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;□□□이란 유해 &amp;middot; 위험 요인이 부상 또는 질병으로 이어질 수 있는 가능성과 중대성을 조합한 것을 의미합니다. &amp;rsquo;가능성&amp;rsquo; 은 작업자의 부상 &amp;middot; 질병 발생의 확률을 의미하며, 노출 빈도 &amp;middot; 시간, 유해 &amp;middot; 위험한 사건의 발생 확률, 피해의 회피 &amp;middot; 제한 가능성을 고려해야 합니다. '중대성&amp;rsquo; 은 부상 &amp;middot; 질병이 발생했을 때 미치는 영향의 정도를 의미하며 부상 또는 건강장해의 정도, 치료 기간, 후유 장해 유무, 피해의 범위를 고려해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3&lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;/100&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;위험성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;11 다음 중 직무스트레스에 의한 직무에 대한 변화가 아닌 것은?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 업무의 몰입도 증가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 높은 결근율, 이직율&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 낮은 수행성과 생산성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 조기퇴직과 질병 퇴직 증가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;1번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;12 다음은 무엇에 대한 설명인가? 빈 칸에 알맞은 답을 쓰시오.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;□□□□란 근로자가 산업재해 발생의 급박한 위험이 발생할 시, 즉시 작업을 중단하고 긴급대피 할 수 있다는 것이다.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4&lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;/100&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;작업중지&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;13 다음은 산업안전보건관리비 중 본사 사용비에 대한 설명이다. 빈 칸에 들어갈 숫자를 쓰시오.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;본사 사용비로 사용이 가능한 항목은 안전만을 전담으로 하는 별도 조직을 갖춘 업체의 본사에서 산업안전보건관리비 사용 전체 항목과 안전전담부서 전담직원 인건비 및 업무수행 출장비로, 계상된 안전관리비의 □%를 초과할 수 없다.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;/100&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;5&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;기술지도비로 사용이 가능한 항목은 재해예방 전문지도기관에 지급하는 기술지도 비용입니다. 반대로 사용불가항목은 총 기술지도 대가가 계상된 산업안전보건관리비 총액의 20%를 초과한 경우이며, 이럴 경우 기술지도의 횟수조정이 가능합니다. 본사 사용비로 사용이 가능한 항목은 안전만을 전담으로 하는 별도 조직을 갖춘 업체의 본사에서 산업안전보건관리비 사용 전체 항목과 안전전담부서 전담직원 인건비 및 업무수행 출장비로, 계상된 안전관리비의 5%를 초과할 수 없습니다. 반대로 사용불가항목은 안전보건관리만을 전담하는 부서가 조직되어 있지 않은 경우, 전담부서에 소속된 직원이 안전보건관리 외의 다른 업무를 병행하는 경우가 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;14 [O/X 문제] 건설현장 진출입로에서 공사차량의 출입을 유도하거나 현장외부의 도로 중앙에서 공사용 차량과 일반통행차량과의 사고를 방지하는 신호자의 인건비는 산업안전보건법에서의 산업안전보건관리비로는 사용이 가능하다.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. O&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. X&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;2번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;건설현장 진출입로에서 공사차량의 출입을 유도하거나 현장외부의 도로 중앙에서 공사용 차량과 일반통행차량과의 사고를 방지하는 신호자의 인건비는 산업안전보건법에서의 산업안전보건관리비로는 사용이 불가능하고, 건설기술 진흥법의 안전관리비로 사용이 가능한데요, 이는 산업안전보건법에서의 산업안전보건관리비는 작업자의 안전과 보건에 관련한 비용을 목적으로 하도록 규정되어 있기 때문이라 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;15 다음 중 안전사고 대응 행동요령 기본원칙 3단계, 도움요청 시 해야하는 구체적 지시가 아닌 것은 무엇인가?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 구조대 신고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 주변 위험물 제거&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 본인의 소속 안내&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 군중 정리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;3번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;도움 요청 시에는 구체적 지시가 필요한데요. 구조대 신고, 구조대 유도, 군중 정리, 주변 위험물 제거, 응급처치에 필요한 도구 및 재료 확보, 처치 보조 등의 임무를 지정해주도록 합니다. 이 중 가장 중요한 것이 구조대에 신고하는 것인데요, 신고를 할 때는 당황하지 말고 침착하게 사고 위치와 부상자 상태에 대해 정확하게 설명합니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;16 다음은 무엇에 대한 설명인가? 빈 칸에 알맞은 답을 쓰시오.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;&quot;□□이란 병원성 미생물 즉 병원체가 숙주 내에서 분열 증식하고 있는 상태로 그 결과 사람에게 질병이나 면역반응을 일으키는 것을 의미한다.&quot; (5점)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2&lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;/100&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;감염&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;감염이란 병원성 미생물, 즉 병원체가 숙주 내에서 분열 증식하고 있는 상태로 그 결과 사람에게 질병이나 면역반응을 일으키는 것을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;17 다음은 빈칸에 들어갈 단어는 무엇인가? (초성: ㅇㅈㅎ)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;산업재해 예방 능력을 제대로 갖추지 못한 영세업체가 도급을 받고, 영세업체의 근로자가 산업재해를 당하는 문제가 빈번하게 발생하고 있는데, 이는 &amp;lsquo;위험의 □□□&amp;rsquo;라고 불리며 사회적 지탄의 대상이 되기도 합니다.&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3&lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;/100&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;외주화&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;최근에는 산업재해 예방 능력을 제대로 갖추지 못한 영세업체가 도급을 받고, 영세업체의 근로자가 산업재해를 당하는 문제가 빈번하게 발생하고 있는데, 도급사업으로 인한 수급인 근로자의 산업재해는 도급인의 경제적 손실 및 법적 책임과 관련되어 있으며 &amp;lsquo;위험의 외주화&amp;rsquo; 라는 사회적 지탄의 대상이 되기도 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;18 [O/X 문제] 도급사업 산업재해의 예방의 책임은 전적으로 도급자에게 있다.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. O&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. X&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;2번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;도급자와 수급자는 산업재해 예방을 위해서 원 &amp;middot; 하도급 간의 안전보건시스템을구축하여 유기적인 산재예방활동을 펼쳐야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;19 다음 중 사고 유형에 관계없이 가장 먼저해야 할 행동은 무엇인가?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&amp;nbsp;(5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 119 혹은 사내 구조대 신고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 부서장에게 보고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 자신의 안전확보를 위한 자리 이탈&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 지인에게 도움 요청&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;1번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;사고 유형에 관계없이 가장 먼저 해야 할 행동은 119 혹은 사내 구조대에 신고하기 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232; background-color: #9feec3;&quot;&gt;20 다음은 무엇에 대한 설명인가? 빈 칸에 알맞은 답을 쓰시오.&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;□□□□□□□□□는 공사종류 및 규모에 따라 일정금액을 도급금액에 별도로 계상하도록 해 시공자가 건설공사 중에 안전관리자 인건비, 안전시설비, 기술 지도비 등에 사용함으로써 재해예방에 기여하는 비용을 말한다. (5점)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;9&lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;/100&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #00bfae;&quot;&gt;해설 닫기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #323232;&quot;&gt;정답 : &lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;산업안전보건관리비&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #323232;&quot;&gt;해설&lt;/span&gt;&lt;span style=&quot;color: #323232;&quot;&gt;사업장에서 근무하는 근로자의 산업재해와 건강장해를 예방하기 위한 목적으로 건설사업장 및 본사 안전전담부서에서 사용하는 돈을 산업안전보건관리비라고 하는데요. 산업안전보건관리비는 건설공사 발주자가 건설공사 종류 및 규모에 따라 일정금액을 도급금액에 별도로 계상, 즉 예산 편성에 반영하도록 해 시공자가 건설공사 중에 안전관리자 인건비, 안전시설비, 기술지도비 등에 사용함으로써 재해예방에 기여하는 데 그 목적이 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>나의 이야기/사회 및 생활</category>
      <category>2022년 3분기 비사무직</category>
      <category>감염</category>
      <category>비말감염</category>
      <category>산업안전보건관리비</category>
      <category>산업안전보건교육</category>
      <category>산업재해</category>
      <category>위험성평가</category>
      <category>위험의 외주화</category>
      <category>직무스트레스</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/203</guid>
      <comments>https://windflex.tistory.com/203#entry203comment</comments>
      <pubDate>Thu, 25 Aug 2022 18:39:18 +0900</pubDate>
    </item>
    <item>
      <title>[Mac+Chrome] 구글 독스 한글 깨짐 현상 (자/모분리)</title>
      <link>https://windflex.tistory.com/202</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3uAns/btrH1ANera0/HuttufkWcXs9hKOYNwlFk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3uAns/btrH1ANera0/HuttufkWcXs9hKOYNwlFk0/img.png&quot; data-alt=&quot;구글독스 (mac)에서 한글 깨짐 현상을 수정해 보자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3uAns/btrH1ANera0/HuttufkWcXs9hKOYNwlFk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3uAns%2FbtrH1ANera0%2FHuttufkWcXs9hKOYNwlFk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;358&quot; height=&quot;358&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구글독스 (mac)에서 한글 깨짐 현상을 수정해 보자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;크롬(Chrome)에서 구글독스 (Google Docs) 한글이 깨지다니....&lt;br /&gt;&lt;/span&gt;똑같은 구글제품에서 깨지면 어떻하나...&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;필자는 MacOS + 크롬(Chrome) 브라우저를 주 인터넷 환경으로 사용하고 있습니다. 그리고, 정돈되기 전의 글들, 로깅, 메모 등은 구글닥스를 사용합니다. &lt;b&gt;그런데, 간혹~ 아주 간혹~ 크롬 브라우저에서 구글독스를 사용하면, 한글이 깨지는 현상이 발생합니다. 과거의 한글조합형 문자의 깨진 문자를 보는듯 하군요.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ㅇㅗㄴㅡㄹㅇㅡㅣ ㅇㅣㄹㄱㅣ&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;흐음....&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그런데, 이게 꼭 항상 그런것은 아니라서, 대충 크롬이 아닌 사파리/파이어폭스 등 다른 브라우저를 사용하다가, 크롬으로 다시 돌아오면 잘되는 경우가 좀 있습니다. PC를 잘 끄지않고 &quot;잠자기&quot;/&quot;대기&quot;를 자주 사용하는지라, 세팅값이 변경되는 경우가 별로 없거든요. 그런데, 오늘 오랜만에 OS업데이트하고 재부팅 했더니 다시 이러한 현상이 발생하더군요... 에효~&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;방법을 찾아봤고, 내용을 공유합니다. 근본적으로 방법은 크롬 브라우저의 세팅 플래그 값을 최화 하는 방안입니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;b&gt;크롬 브라우저 프래그 초기화&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;방법은 아주 간단합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1) 크롬 브라우저 주소입력란에, 다음을 입력한다. : &lt;span style=&quot;background-color: #f89009;&quot;&gt;chrome://flags/#enable-npapi&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2) &lt;span style=&quot;background-color: #f89009;&quot;&gt;&quot;Reset All&quot;&lt;/span&gt; 버튼을 누른다. 자동으로 브라우저창이 닫혔다 재기동 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3) 구글독스에서 한글입력이 제대로 동작하는지 확인한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 브라우저 주소 : &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;chrome://flags/#enable-npapi 입력 후, 아래 &quot;Reset all&quot; 버튼을 눌러 줍니다.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuhOmM/btrH9H4RM82/OukOHnRkS7sKfKcfUxk1R0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuhOmM/btrH9H4RM82/OukOHnRkS7sKfKcfUxk1R0/img.png&quot; data-alt=&quot;크롬브라우저의 플래그 설정 페이지 :&amp;amp;amp;nbsp;chrome://flags/#enable-npapi&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuhOmM/btrH9H4RM82/OukOHnRkS7sKfKcfUxk1R0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuhOmM%2FbtrH9H4RM82%2FOukOHnRkS7sKfKcfUxk1R0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;605&quot; height=&quot;433&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;크롬브라우저의 플래그 설정 페이지 :&amp;amp;nbsp;chrome://flags/#enable-npapi&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 구글독스 한글 입력 결과 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;426&quot; data-origin-height=&quot;226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRIZy7/btrH3Q2bPXN/Ho3GwazySGe1dRcwwMTvoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRIZy7/btrH3Q2bPXN/Ho3GwazySGe1dRcwwMTvoK/img.png&quot; data-alt=&quot;구글독스에서 한글 입력이 이제 잘 되네요.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRIZy7/btrH3Q2bPXN/Ho3GwazySGe1dRcwwMTvoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRIZy7%2FbtrH3Q2bPXN%2FHo3GwazySGe1dRcwwMTvoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;426&quot; height=&quot;226&quot; data-origin-width=&quot;426&quot; data-origin-height=&quot;226&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구글독스에서 한글 입력이 이제 잘 되네요.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;[ 관련 글]&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/211&quot;&gt;2022.11.07 - [IT 이야기] - [Mac OS] 배터리 충전 관리 (limiter) - ft. AlDente&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/210&quot;&gt;2022.11.07 - [IT 이야기/IT 상식] - [맥북 Ventura] 배터리 잔량 퍼센트 보기 - ft. 제어 센터&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/209&quot;&gt;2022.10.31 - [IT 이야기/IT 상식] - [MacOS] 백틱(`) 입력 - 원화(₩)입력 변경 to BQuote(`)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/208&quot;&gt;2022.10.20 - [IT 이야기/IT 상식] - [MacOS - ZSH] 유용한 플러그인 2종 - 자동완성/하이라이트&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/202&quot;&gt;2022.07.25 - [IT 이야기] - [Mac+Chrome] 구글 독스 한글 깨짐 현상 (자/모분리)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/195&quot;&gt;2022.06.29 - [IT 이야기/IT 상식] - [맥북-NTFS] 맥북에서 윈도우 외장하드(NTFS) 쓰기(mount) - 모든버전 사용 가능&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/157&quot;&gt;2021.01.21 - [IT 이야기/IT 상식] - 맥(MacOS)에서 특수문자/한자 입력 하기 -☆ ★ ○ ●&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기</category>
      <category>Mac Chrome 한글</category>
      <category>Mac 크롬 구글독스 한글</category>
      <category>Mac 한글 깨짐</category>
      <category>구글독스 Mac 한글</category>
      <category>구글독스 맥</category>
      <category>구글독스 한글 깨짐</category>
      <category>구글독스 한글 자음 모음 분리</category>
      <category>크롬 구글독스 한글 자모분리</category>
      <category>크롬 플래그 세팅</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/202</guid>
      <comments>https://windflex.tistory.com/202#entry202comment</comments>
      <pubDate>Mon, 25 Jul 2022 10:21:35 +0900</pubDate>
    </item>
    <item>
      <title>[AWS 교육 요약] Developing on AWS (3/3)</title>
      <link>https://windflex.tistory.com/201</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Python은 Flask / FastAPI / Django 등에서 각 Web Application 의 함수를 Routing해 준다. 그러나, AWS Lambda와 같은 Serverless 방식으로 Function을 구동한다면 어떻게 라우팅 해 줄 수 있을까?&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AWS에서 제시하는 답은 API Gateway를 사용하라.!!!&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로 Routing을 처리하는 과정에서 L7 Layer 장비가 해 줄수있는 Application에서의 추가기능을 제공한다. 대표적으로, Request의 Validation 점검, Response의 변형, 그리고 prod/test 등의 deploy 관리 등이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;API Gateway를 사용한 솔루션 개발&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림으로 도식화하여 보자. Amazon API Gateway를 사용하면 다음 그림과 같이 Method (GET / POST) 등에 따라서 Lambda 함수로의 매핑을 해 주는 기능을 한다. 일반 웹프레임워크에서 라우팅 기능이라고 보면 되겠다. 아래 그림에서는 GET Method로 호출할 때는 list 함수를, POST Method 호출할 때는 createUpdate 함수를 호출한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;878&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EauaL/btrHg2IiJJR/bbTSDvt5vfKU4bwCFwbbbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EauaL/btrHg2IiJJR/bbTSDvt5vfKU4bwCFwbbbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EauaL/btrHg2IiJJR/bbTSDvt5vfKU4bwCFwbbbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEauaL%2FbtrHg2IiJJR%2FbbTSDvt5vfKU4bwCFwbbbK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;486&quot; height=&quot;324&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;878&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API Gateway를 실행하기 위해서는,&amp;nbsp;&quot;AWS Service &amp;gt; API Gateway &amp;gt; Create API 버튼 클릭&quot; 으로 새로운 API를 생성한다.&amp;nbsp; 그 다음 WebSocket , REST API 등 여러 API 유형이 나오는데, 가장 익숙한 REST API 항목에서 &quot;Build&quot;를 눌러서 API를 생성하도록 하자. 다음으로 나오는 페이지에서는 간략히 API이름을 입력해 주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/swTCs/btrHiGZOn8o/AOGZLQ9Kar9KaxIxu7Oxx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/swTCs/btrHiGZOn8o/AOGZLQ9Kar9KaxIxu7Oxx1/img.png&quot; data-origin-width=&quot;1199&quot; data-origin-height=&quot;293&quot; data-is-animation=&quot;false&quot; style=&quot;width: 55.0959%; margin-right: 10px;&quot; data-widthpercent=&quot;55.74&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/swTCs/btrHiGZOn8o/AOGZLQ9Kar9KaxIxu7Oxx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FswTCs%2FbtrHiGZOn8o%2FAOGZLQ9Kar9KaxIxu7Oxx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1199&quot; height=&quot;293&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tEDnM/btrHiFfxGRe/tFD627Pz7v42COcbkraNl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tEDnM/btrHiFfxGRe/tFD627Pz7v42COcbkraNl0/img.png&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;209&quot; data-is-animation=&quot;false&quot; style=&quot;width: 43.7413%;&quot; data-widthpercent=&quot;44.26&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tEDnM/btrHiFfxGRe/tFD627Pz7v42COcbkraNl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtEDnM%2FbtrHiFfxGRe%2FtFD627Pz7v42COcbkraNl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 가 생성되었다면, 다음과 같은 프로세스로 진행 하면된다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Resource 생성&lt;/li&gt;
&lt;li&gt;Method 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Create Resource에는 &quot;notes&quot;라는 이름으로 생성해 주자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Create Method에서는 GET 또는 POST 등의 Method를 선택하고, 해당되는 Lambda Function을 설정해 주는 것이 핵심이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AFKna/btrHeV46tTm/NeYUiQAzIRtw2PLEccLNaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AFKna/btrHeV46tTm/NeYUiQAzIRtw2PLEccLNaK/img.png&quot; data-origin-width=&quot;231&quot; data-origin-height=&quot;313&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;34.61&quot; style=&quot;width: 34.2045%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AFKna/btrHeV46tTm/NeYUiQAzIRtw2PLEccLNaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAFKna%2FbtrHeV46tTm%2FNeYUiQAzIRtw2PLEccLNaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;231&quot; height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xzXhM/btrHidjnrOo/X5kD09UfrS6iXjPjEifdU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xzXhM/btrHidjnrOo/X5kD09UfrS6iXjPjEifdU0/img.png&quot; data-origin-width=&quot;205&quot; data-origin-height=&quot;147&quot; data-is-animation=&quot;false&quot; style=&quot;width: 64.6327%;&quot; data-widthpercent=&quot;65.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xzXhM/btrHidjnrOo/X5kD09UfrS6iXjPjEifdU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxzXhM%2FbtrHidjnrOo%2FX5kD09UfrS6iXjPjEifdU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;205&quot; height=&quot;147&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G1NOk/btrHiDvqdDu/0USK9r4tJm2cFSMPRvQOZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G1NOk/btrHiDvqdDu/0USK9r4tJm2cFSMPRvQOZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G1NOk/btrHiDvqdDu/0USK9r4tJm2cFSMPRvQOZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG1NOk%2FbtrHiDvqdDu%2F0USK9r4tJm2cFSMPRvQOZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1007&quot; height=&quot;518&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;987&quot; data-origin-height=&quot;731&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxStcq/btrHiGFBM2w/49QxbYZddmY6xWORNV0hRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxStcq/btrHiGFBM2w/49QxbYZddmY6xWORNV0hRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxStcq/btrHiGFBM2w/49QxbYZddmY6xWORNV0hRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxStcq%2FbtrHiGFBM2w%2F49QxbYZddmY6xWORNV0hRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;987&quot; height=&quot;731&quot; data-origin-width=&quot;987&quot; data-origin-height=&quot;731&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;198&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d9BqPp/btrHg32eqXv/NRSaD9GUnW2JQ696sURip1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d9BqPp/btrHg32eqXv/NRSaD9GUnW2JQ696sURip1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d9BqPp/btrHg32eqXv/NRSaD9GUnW2JQ696sURip1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd9BqPp%2FbtrHg32eqXv%2FNRSaD9GUnW2JQ696sURip1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;198&quot; height=&quot;243&quot; data-origin-width=&quot;198&quot; data-origin-height=&quot;243&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;473&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ew18F5/btrHdILOX1r/YKtTIoJzOvp1dgSwD2BEQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ew18F5/btrHdILOX1r/YKtTIoJzOvp1dgSwD2BEQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ew18F5/btrHdILOX1r/YKtTIoJzOvp1dgSwD2BEQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Few18F5%2FbtrHdILOX1r%2FYKtTIoJzOvp1dgSwD2BEQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;711&quot; height=&quot;473&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;473&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1223&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvfpoH/btrHicY5fQ7/XjnyYOm6XA1IPx3a9eoJOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvfpoH/btrHicY5fQ7/XjnyYOm6XA1IPx3a9eoJOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvfpoH/btrHicY5fQ7/XjnyYOm6XA1IPx3a9eoJOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvfpoH%2FbtrHicY5fQ7%2FXjnyYOm6XA1IPx3a9eoJOk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1223&quot; height=&quot;530&quot; data-origin-width=&quot;1223&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1199&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rdLcM/btrHhcyjdmK/FqbZdzUDVCCeBenBH6lup0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rdLcM/btrHhcyjdmK/FqbZdzUDVCCeBenBH6lup0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rdLcM/btrHhcyjdmK/FqbZdzUDVCCeBenBH6lup0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrdLcM%2FbtrHhcyjdmK%2FFqbZdzUDVCCeBenBH6lup0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1199&quot; height=&quot;702&quot; data-origin-width=&quot;1199&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Cognito 인증 애플리케이션 구축 (Practice 06)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;846&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3dXvD/btrHidYApGf/bGXQiKOTho21w4yJtHzrq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3dXvD/btrHidYApGf/bGXQiKOTho21w4yJtHzrq1/img.png&quot; data-alt=&quot;실습에서 목표로하는 아키텍처&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3dXvD/btrHidYApGf/bGXQiKOTho21w4yJtHzrq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3dXvD%2FbtrHidYApGf%2FbGXQiKOTho21w4yJtHzrq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1326&quot; height=&quot;846&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;846&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실습에서 목표로하는 아키텍처&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lambda에는 이미 함수가 구현/등록되어 있다. 이 함수들을 연결하는 API Gateway는 샘플로 list 함수만 연결이 되어 있는 상황인다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;913&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4TS69/btrHj3tI7sr/W4dLYN3dQalDoM8a7Ghbp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4TS69/btrHj3tI7sr/W4dLYN3dQalDoM8a7Ghbp0/img.png&quot; data-alt=&quot;Lambda에는 이미 함수가 구현되어 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4TS69/btrHj3tI7sr/W4dLYN3dQalDoM8a7Ghbp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4TS69%2FbtrHj3tI7sr%2FW4dLYN3dQalDoM8a7Ghbp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;913&quot; height=&quot;476&quot; data-origin-width=&quot;913&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Lambda에는 이미 함수가 구현되어 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tw1s8/btrHiE3mU3u/VjVUfWyfb2cAgBfFCkkBxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tw1s8/btrHiE3mU3u/VjVUfWyfb2cAgBfFCkkBxk/img.png&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;214&quot; data-is-animation=&quot;false&quot; style=&quot;width: 64.3074%; margin-right: 10px;&quot; data-widthpercent=&quot;65.06&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tw1s8/btrHiE3mU3u/VjVUfWyfb2cAgBfFCkkBxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftw1s8%2FbtrHiE3mU3u%2FVjVUfWyfb2cAgBfFCkkBxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;660&quot; height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WJJke/btrHiG0F9ox/zatfxt4Yf93TlwYghRBHY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WJJke/btrHiG0F9ox/zatfxt4Yf93TlwYghRBHY0/img.png&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;532&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;34.94&quot; style=&quot;width: 34.5299%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WJJke/btrHiG0F9ox/zatfxt4Yf93TlwYghRBHY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWJJke%2FbtrHiG0F9ox%2Fzatfxt4Yf93TlwYghRBHY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;881&quot; height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;기본적으로 API Gateway가 구동되어 있다.(좌), 그러나, API Gateway는 list 함수만 기본 설정 되어 있다. (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 환경에서 우리는, Cogniton를 연결하여 인증을 토큰을 받고 이것을 API Gateway와 연결하여 인증이 연동될 수 있도록 해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Amazon Cognito를 사용하여 사용자풀 (UserPool) 과 앱 클라이언트 (App Client)를 생성&lt;/li&gt;
&lt;li&gt;새사용자를 추가하고, Cognito CLI를 이용하여 로그인 (가능 여부 확인)&lt;/li&gt;
&lt;li&gt;API Gateway에서 Amazon Cognito를 권한 부여자로 등록 (메서드 구성)&lt;/li&gt;
&lt;li&gt;API 호출 중에, JWT (Just-in time Web Token) 인증 토큰 생성 확인&lt;/li&gt;
&lt;li&gt;Amazon Cognito 및 API Gateway 구성을 사용하도록 웹 Front-End 애플리케이션 (React) 설정, 기능확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) Congito User Pool 생성&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FwYfu/btrHiTFjIpt/KlPS6TbrCBHDziyjNSl3F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FwYfu/btrHiTFjIpt/KlPS6TbrCBHDziyjNSl3F0/img.png&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;400&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;35.24&quot; style=&quot;width: 34.8296%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FwYfu/btrHiTFjIpt/KlPS6TbrCBHDziyjNSl3F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFwYfu%2FbtrHiTFjIpt%2FKlPS6TbrCBHDziyjNSl3F0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;404&quot; height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VRz0a/btrHiFgiLpM/7mOSHMzjB4yYULBVp9xni0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VRz0a/btrHiFgiLpM/7mOSHMzjB4yYULBVp9xni0/img.png&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;417&quot; data-is-animation=&quot;false&quot; style=&quot;width: 64.0076%;&quot; data-widthpercent=&quot;64.76&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VRz0a/btrHiFgiLpM/7mOSHMzjB4yYULBVp9xni0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVRz0a%2FbtrHiFgiLpM%2F7mOSHMzjB4yYULBVp9xni0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;774&quot; height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Cognito User Pool 생성. UserPool 선택 (좌), Password Policy (우) 테스트를 쉽게 하기 위하여 보안수준을 낮추고 보안체크 기능을 비활성화 했다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mtU1F/btrHfRV5vir/x9uDl8UMngIwxJf8Zx1Dz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mtU1F/btrHfRV5vir/x9uDl8UMngIwxJf8Zx1Dz1/img.png&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;255&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.4042%; margin-right: 10px;&quot; data-widthpercent=&quot;54.03&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mtU1F/btrHfRV5vir/x9uDl8UMngIwxJf8Zx1Dz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmtU1F%2FbtrHfRV5vir%2Fx9uDl8UMngIwxJf8Zx1Dz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;766&quot; height=&quot;255&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K0VTC/btrHiG0K6P8/So1rgr0vZsDFqnr2lBjhsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K0VTC/btrHiG0K6P8/So1rgr0vZsDFqnr2lBjhsK/img.png&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;315&quot; data-is-animation=&quot;false&quot; style=&quot;width: 45.433%;&quot; data-widthpercent=&quot;45.97&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K0VTC/btrHiG0K6P8/So1rgr0vZsDFqnr2lBjhsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK0VTC%2FbtrHiG0K6P8%2FSo1rgr0vZsDFqnr2lBjhsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;805&quot; height=&quot;315&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Cognito User Pool 생성 결과: User Pool (좌), App Client (우), 각각의 표기된 ID 문자열 값은 이후 연동에 사용되므로 따로 저장해 두고 사용하자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) User Pool 에 새 사용자 등록&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동작 가능성을 점검하기 위해서, aws cli를 통해서 새 사용자 등록을 처리한다. 이후는 web application에서 처리해야 할 것이다.&amp;nbsp; cli명령어는 &quot;aws cognito-idp sign-up&quot; 명령어를 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657788759188&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws cognito-idp sign-up --client-id &amp;lt;App 클라이언트ID&amp;gt; --username student --password student&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;username과 password는 &quot;student&quot;로 고정하여 테스트 하였음.&lt;br /&gt;위의 aws cli를 사용하면, 사용자&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;App 클라이언트 ID&amp;gt;라고 표기한 곳은 위 User Pool 생성 결과에서 표기된 Client ID를 표기한다. 다음과 같이, 필요한 내용은 변수로 만들어서 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657789081814&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ apiURL='[apiURL]'
$ CognitoPoolId='[Cognito Pool Id]'
$ AppClientId='[App Client Id]'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 포스팅의 경우, 변수는 다음과 같다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657789140677&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiURL='https://tr67vt4vi6.execute-api.us-west-2.amazonaws.com/Prod'
CognitoPoolId='us-west-2_31xxxxxxT'
AppClientId='47frcxxxxxxxxxxxxxxxxxxvo5sp'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수가 설정 되었다면, cli명령어는 변수를 사용하여 다시 작성할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1657789947243&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws cognito-idp sign-up --client-id $AppClientId --username student --password student
결과값 : 
{
    &quot;UserConfirmed&quot;: false,
    &quot;UserSub&quot;: &quot;16c1e566-f828-48ab-927b-c43252ced067&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제, 사용자풀 (User Pool)에 사용자가 등록이 되었다. AWS Console &amp;gt; Cognito &amp;gt; User Pool 화면에서, 우리가 생성한 UserPool 이름 (PollyNotesPool)의 User탭에 가면 사용자가 아래와 같이 등록되어 있는 것을 확인 할수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;211&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMeJBS/btrHfRoqCFf/HeO5lSCBwdIN11niE4wuR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMeJBS/btrHfRoqCFf/HeO5lSCBwdIN11niE4wuR1/img.png&quot; data-alt=&quot;User Pool 에 새사용자를 등록한 결과. Unconfirmed 상태이다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMeJBS/btrHfRoqCFf/HeO5lSCBwdIN11niE4wuR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMeJBS%2FbtrHfRoqCFf%2FHeO5lSCBwdIN11niE4wuR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;997&quot; height=&quot;211&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;211&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;User Pool 에 새사용자를 등록한 결과. Unconfirmed 상태이다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나 자세히 보면 &quot;Confirmation status&quot;가 아직 &quot;Unconfirmed&quot;되어 있는 것을 알 수 있다.&amp;nbsp; 관리자(Admin)이 승인을 해야 최종 &quot;Confirm&quot;이 되는 프로세스를 가지고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다시 Cli명령어를 사용하여 Admin의 Confirm을 해주자.&lt;/p&gt;
&lt;pre id=&quot;code_1657790669669&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws cognito-idp admin-confirm-sign-up --user-pool-id $CognitoPoolId --username student&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;필요한 중요 정보는 Pool ID와 승인할 사용자의 이름이다. 사용자 이름은 당연한 것이고, Pool ID는 여러 Pool이 있을 경우 이것을 지칭해야 하므로 필요할 것이다. 그러나, 의문점은 사용자 등록은 App Client ID인데, 승인은 왜 Pool ID를 사용하는가?&lt;br /&gt;App Client ID는 당연히 Pool ID에 종속되어 있기 때문에 연동되어도 상관은 없으나, 일관성이 부족한것은 아닐까?&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;211&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lrjg9/btrHkpwIJNx/eOMGWOVH6KJQj35Dq8SbB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lrjg9/btrHkpwIJNx/eOMGWOVH6KJQj35Dq8SbB0/img.png&quot; data-alt=&quot;User Pool에 새사용자 등록 후, Admin의 승인 처리 결과: Confirmed로 변경되었다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lrjg9/btrHkpwIJNx/eOMGWOVH6KJQj35Dq8SbB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flrjg9%2FbtrHkpwIJNx%2FeOMGWOVH6KJQj35Dq8SbB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;997&quot; height=&quot;211&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;211&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;User Pool에 새사용자 등록 후, Admin의 승인 처리 결과: Confirmed로 변경되었다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) Amazon Cognito 동작 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 진행한 결과를 테스트 하기 위해서, 간략한 테스트용 웹페이지를 제공한다. 실습에 기본 생성되어 있는 S3에 들어가 보면, Public으로 정적 웹호스팅을 하고 있는 2개의 버킷을 확인 할 수 있는데, 이중 &quot;testlogin...&quot;으로 표기된 웹페이지를 열어본 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXRdGk/btrHfR27MsA/HRyEutLKe1rFlj8F08raY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXRdGk/btrHfR27MsA/HRyEutLKe1rFlj8F08raY0/img.png&quot; data-origin-width=&quot;1073&quot; data-origin-height=&quot;313&quot; data-is-animation=&quot;false&quot; style=&quot;width: 62.5836%; margin-right: 10px;&quot; data-widthpercent=&quot;63.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXRdGk/btrHfR27MsA/HRyEutLKe1rFlj8F08raY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXRdGk%2FbtrHfR27MsA%2FHRyEutLKe1rFlj8F08raY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1073&quot; height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u3EEt/btrHiFOn0eN/A8XCiKjpHViJYq00NcKEUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u3EEt/btrHiFOn0eN/A8XCiKjpHViJYq00NcKEUK/img.png&quot; data-origin-width=&quot;421&quot; data-origin-height=&quot;212&quot; data-is-animation=&quot;false&quot; style=&quot;width: 36.2536%;&quot; data-widthpercent=&quot;36.68&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u3EEt/btrHiFOn0eN/A8XCiKjpHViJYq00NcKEUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu3EEt%2FbtrHiFOn0eN%2FA8XCiKjpHViJYq00NcKEUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;421&quot; height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TestLogin 웹페이지의 화면은 다음과 같다. Pool ID와, App Client ID, Username, Passworkd를 입력하면, Cognito가 보내준 Access Token을 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqXx65/btrHjcLGHcH/Ob9ToIWmXkl6m1rjVR6KB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqXx65/btrHjcLGHcH/Ob9ToIWmXkl6m1rjVR6KB1/img.png&quot; data-origin-width=&quot;567&quot; data-origin-height=&quot;436&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;45.06&quot; data-filename=&quot;blob&quot; style=&quot;width: 44.5327%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqXx65/btrHjcLGHcH/Ob9ToIWmXkl6m1rjVR6KB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqXx65%2FbtrHjcLGHcH%2FOb9ToIWmXkl6m1rjVR6KB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;567&quot; height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ATxbR/btrHhbmHaY5/J4W0d62g6ePDkotTA1P3H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ATxbR/btrHhbmHaY5/J4W0d62g6ePDkotTA1P3H1/img.png&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;705&quot; data-is-animation=&quot;false&quot; style=&quot;width: 54.3045%;&quot; data-widthpercent=&quot;54.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ATxbR/btrHhbmHaY5/J4W0d62g6ePDkotTA1P3H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FATxbR%2FbtrHhbmHaY5%2FJ4W0d62g6ePDkotTA1P3H1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1118&quot; height=&quot;705&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;인증 성공하면, &quot;.getIdToken().getJwtToken()&quot;메서드가 호출된다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) API Gateway - Cognito를 권한 부여자로 사용하도록 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 Amazon Cognito를 설정하여 1) User Pool를 생성, 2) 사용자를 User Pool에 등록, 3) 사용자 로그인 요청 시 JWT 발행 테스트 하였다. 이제 Cognito에서 발행해 주는 JWT 토큰으로 API Gateway에서 인증되도록 연동해 주어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUFxZP/btrHiWCDCsI/P1SpmFPWZIB2imFOevVWyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUFxZP/btrHiWCDCsI/P1SpmFPWZIB2imFOevVWyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUFxZP/btrHiWCDCsI/P1SpmFPWZIB2imFOevVWyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUFxZP%2FbtrHiWCDCsI%2FP1SpmFPWZIB2imFOevVWyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;660&quot; height=&quot;214&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS service &amp;gt; API Gateway 화면에서 이미 생성되어 있는 우리의 API Gateway ( &quot;PollyNotesAPI&quot; ) 를 클릭해 주자.&lt;/li&gt;
&lt;li&gt;그 다음 왼쪽 메뉴 &amp;gt; Authorizers 메뉴 &amp;gt; &quot;Create new Authorizer&quot; 를 클릭하자. 여기에서 우리는 Cognito를 인증기로 연동해 주는 작업을 할 것이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Create Authorizer 버튼을 누르면, 아래 그림 (우) 같이 Name, Type, Cognito User Pool, Tocken Source를 입력해 주고 Create 버튼을 눌러주자.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMXgVi/btrHi4fZzz9/QuwBV9VnT4jcKKKI3eBB4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMXgVi/btrHi4fZzz9/QuwBV9VnT4jcKKKI3eBB4k/img.png&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;443&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.3753%; margin-right: 10px;&quot; data-widthpercent=&quot;48.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMXgVi/btrHi4fZzz9/QuwBV9VnT4jcKKKI3eBB4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMXgVi%2FbtrHi4fZzz9%2FQuwBV9VnT4jcKKKI3eBB4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;503&quot; height=&quot;443&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKxfEZ/btrHkpqjJVf/B7UKfCoxkZPREvXFT1qCLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKxfEZ/btrHkpqjJVf/B7UKfCoxkZPREvXFT1qCLK/img.png&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;385&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;51.06&quot; style=&quot;width: 50.4619%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKxfEZ/btrHkpqjJVf/B7UKfCoxkZPREvXFT1qCLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKxfEZ%2FbtrHkpqjJVf%2FB7UKfCoxkZPREvXFT1qCLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;456&quot; height=&quot;385&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Authorizer가 생성되면 결과가 아래 그림 (좌)와 같이 나타나고, 테스트를 실행해 볼 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Authorization 항목을 빈칸으로 테스트 하면 당연하게도 401에러와 &quot;Unauthorized request&quot; 메세지를 받는다.&lt;/li&gt;
&lt;li&gt;앞서, cognito test 페이지에서 수신받은 JWT 토큰을 입력해 주면 아래 오른쪽 그림처럼 정상 인증인 된것을 확인 할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0WF3c/btrHlzzfnkA/kkMBpWTEsk8uhCFq3rcMx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0WF3c/btrHlzzfnkA/kkMBpWTEsk8uhCFq3rcMx1/img.png&quot; data-origin-width=&quot;368&quot; data-origin-height=&quot;292&quot; data-is-animation=&quot;false&quot; style=&quot;width: 36.6951%; margin-right: 10px;&quot; data-widthpercent=&quot;37.57&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0WF3c/btrHlzzfnkA/kkMBpWTEsk8uhCFq3rcMx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0WF3c%2FbtrHlzzfnkA%2FkkMBpWTEsk8uhCFq3rcMx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;368&quot; height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnDPl1/btrHlzTx0RX/MVHOYzaxQkDFZqlYKt5Xr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnDPl1/btrHlzTx0RX/MVHOYzaxQkDFZqlYKt5Xr1/img.png&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;390&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.3271%; margin-right: 10px;&quot; data-widthpercent=&quot;33.1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnDPl1/btrHlzTx0RX/MVHOYzaxQkDFZqlYKt5Xr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnDPl1%2FbtrHlzTx0RX%2FMVHOYzaxQkDFZqlYKt5Xr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;433&quot; height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQIE61/btrHiX9q6PP/GVL9JTkdw11KSbRkJkxiI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQIE61/btrHiX9q6PP/GVL9JTkdw11KSbRkJkxiI0/img.png&quot; data-origin-width=&quot;555&quot; data-origin-height=&quot;564&quot; data-is-animation=&quot;false&quot; style=&quot;width: 28.6522%;&quot; data-widthpercent=&quot;29.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQIE61/btrHiX9q6PP/GVL9JTkdw11KSbRkJkxiI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQIE61%2FbtrHiX9q6PP%2FGVL9JTkdw11KSbRkJkxiI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;555&quot; height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;API Gateway Authorizer 생성 결과 (좌), Authorizer Test 결과 : 401 에러 (중), Authorizer Test 결과 200 성공 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API Gateway &amp;gt; 왼쪽 메뉴 API: PollyNotesAPI &amp;gt; Resource 메뉴로 돌아온다. 기존 정의한 /notes의 GET/POST 메소드에 대한 정의가 보인다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;GET Method를 선택하고 &amp;gt; Method Request를 선택해 주자&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdp4eC/btrHidkGlUA/G8a4iKJR9RHxKEShkX5z4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdp4eC/btrHidkGlUA/G8a4iKJR9RHxKEShkX5z4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdp4eC/btrHidkGlUA/G8a4iKJR9RHxKEShkX5z4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbdp4eC%2FbtrHidkGlUA%2FG8a4iKJR9RHxKEShkX5z4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;925&quot; height=&quot;302&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GET method의 Settings &amp;gt; Authorization -&amp;gt; 편집 --&amp;gt; PollyNotesPool (API Gateway의 Authorizer에서 설정해 주었던 이름)&lt;/li&gt;
&lt;li&gt;*선택 후 꼭 옆에 있는 v표시 (확인)를 클릭 해 주어야 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oIlvj/btrHkokFhc1/taPBzdXDpReGm7n1FZPQtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oIlvj/btrHkokFhc1/taPBzdXDpReGm7n1FZPQtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oIlvj/btrHkokFhc1/taPBzdXDpReGm7n1FZPQtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoIlvj%2FbtrHkokFhc1%2FtaPBzdXDpReGm7n1FZPQtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;719&quot; height=&quot;370&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그 다음 다시 상위 메뉴로 나와, Integration Request 메뉴로 들어간다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;967&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/co1kX7/btrHiYAuQee/0VkUFxvfUvcZORQYsIcBgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/co1kX7/btrHiYAuQee/0VkUFxvfUvcZORQYsIcBgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/co1kX7/btrHiYAuQee/0VkUFxvfUvcZORQYsIcBgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fco1kX7%2FbtrHiYAuQee%2F0VkUFxvfUvcZORQYsIcBgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;967&quot; height=&quot;231&quot; data-origin-width=&quot;967&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkRB6q/btrHjyaiCFw/duMEc36eLcHxlSV4UqBKwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkRB6q/btrHjyaiCFw/duMEc36eLcHxlSV4UqBKwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkRB6q/btrHjyaiCFw/duMEc36eLcHxlSV4UqBKwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkRB6q%2FbtrHjyaiCFw%2FduMEc36eLcHxlSV4UqBKwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;570&quot; height=&quot;452&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;기본 템플릿으로&amp;nbsp; {&quot;UserId&quot;: &quot;student&quot;} 가 저장되어 있다. 이것은 모든 UserId를 &quot;student&quot;로 고정하고 있기 때문에, cognito에서 반환하는 username으로 동적 변경해 주는 부분이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qQ9MM/btrHiejCVj0/7t3I3q3UKULDNLyJ4ULr81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qQ9MM/btrHiejCVj0/7t3I3q3UKULDNLyJ4ULr81/img.png&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;216&quot; data-is-animation=&quot;false&quot; style=&quot;width: 28.718%; margin-right: 10px;&quot; data-widthpercent=&quot;29.06&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qQ9MM/btrHiejCVj0/7t3I3q3UKULDNLyJ4ULr81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqQ9MM%2FbtrHiejCVj0%2F7t3I3q3UKULDNLyJ4ULr81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;272&quot; height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MI68J/btrHiYAv8iX/KyNagNf7BSJ1yvkJmkdWz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MI68J/btrHiYAv8iX/KyNagNf7BSJ1yvkJmkdWz0/img.png&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;375&quot; data-is-animation=&quot;false&quot; style=&quot;width: 70.1192%;&quot; data-widthpercent=&quot;70.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MI68J/btrHiYAv8iX/KyNagNf7BSJ1yvkJmkdWz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMI68J%2FbtrHiYAv8iX%2FKyNagNf7BSJ1yvkJmkdWz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1153&quot; height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1169&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NsRJN/btrHjulgxnk/gMR4LHJFyqLwQo5kf8IbT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NsRJN/btrHjulgxnk/gMR4LHJFyqLwQo5kf8IbT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NsRJN/btrHjulgxnk/gMR4LHJFyqLwQo5kf8IbT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNsRJN%2FbtrHjulgxnk%2FgMR4LHJFyqLwQo5kf8IbT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1169&quot; height=&quot;458&quot; data-origin-width=&quot;1169&quot; data-origin-height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>개발 이야기</category>
      <category>api gateway cognito</category>
      <category>aws api gateway</category>
      <category>AWS cognito api gateway</category>
      <category>AWS 인증 애플리케이션</category>
      <category>cognito api gateway 연동</category>
      <category>cognito user pool 생성</category>
      <category>cognito 인증</category>
      <category>cognito 인증 만들기</category>
      <category>S3 정적 웹호스팅</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/201</guid>
      <comments>https://windflex.tistory.com/201#entry201comment</comments>
      <pubDate>Mon, 18 Jul 2022 11:39:51 +0900</pubDate>
    </item>
    <item>
      <title>Keras get_config 에러</title>
      <link>https://windflex.tistory.com/200</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lMUw9/btrHo6yi22W/Hfs53G2YOzUPAvFbSU5iNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lMUw9/btrHo6yi22W/Hfs53G2YOzUPAvFbSU5iNK/img.png&quot; data-alt=&quot;케라스 커스텀 모델 (keras Custom Model) 만들기. get_config() 에러&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lMUw9/btrHo6yi22W/Hfs53G2YOzUPAvFbSU5iNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlMUw9%2FbtrHo6yi22W%2FHfs53G2YOzUPAvFbSU5iNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;393&quot; height=&quot;393&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;케라스 커스텀 모델 (keras Custom Model) 만들기. get_config() 에러&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Keras Custom Model 에러 : get_config Not Implemented Error&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Keras로 Custom 모델을 생성하고 학습을 하다 보면, &quot;get_config(self)&quot;가 정의되지 않았다는 에러를 만날 때가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;에러가 발생한 구체적인 사례는 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
&amp;lt;ipython-input-87-6c20ab69a27d&amp;gt; in &amp;lt;module&amp;gt;
     13 
     14 
---&amp;gt; 15 history = custom_model.fit( X_train , y_train , batch_size = 32, epochs=nEpochs, 
     16                        validation_data=(X_test, y_test)  ,
     17                        # class_weight=class_weight,

~/anaconda3/lib/python3.8/site-packages/keras/utils/traceback_utils.py in error_handler(*args, **kwargs)
     65     except Exception as e:  # pylint: disable=broad-except
     66       filtered_tb = _process_traceback_frames(e.__traceback__)
---&amp;gt; 67       raise e.with_traceback(filtered_tb) from None
     68     finally:
     69       del filtered_tb

~/anaconda3/lib/python3.8/site-packages/keras/engine/training.py in get_config(self)
   2435 
   2436   def get_config(self):
-&amp;gt; 2437     raise NotImplementedError
   2438 
   2439   @classmethod

NotImplementedError:&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그런데, 당혹스러운 것은 Keras 공식문서에서 Custom Model을 만들때는, get_config()를 구현을 필요로 하지 않기 때문이다. &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;tf.keras.Model&quot;을 상속받아 클래스를 만들고, 생성자(__init__)와 &quot;call()&quot;함수를 구현해 주면 된다.&amp;nbsp;&lt;/span&gt;다음은 Keras 공식문서에서 가이드 하고 있는 Custom Model을 만드는 템플릿이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657888669313&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import tensorflow as tf

class MyModel(tf.keras.Model):

  def __init__(self):
    super().__init__()
    self.dense1 = tf.keras.layers.Dense(4, activation=tf.nn.relu)
    self.dense2 = tf.keras.layers.Dense(5, activation=tf.nn.softmax)

  def call(self, inputs):
    x = self.dense1(inputs)
    return self.dense2(x)

model = MyModel()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;get_config()를 구현해 주어야 하는 경우는, 모델 또는 모델의 weights를 저장해 주는 경우인데, 에러가 발생하는 곳은 Training/Evaluation 경우에 발생해서 의아해 하고 있었다. 다음은 공식 가이드의 내용이다.&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;h4 id=&quot;configuring-the-savedmodel&quot; data-ke-size=&quot;size20&quot;&gt;Configuring the SavedModel&lt;/h4&gt;
&lt;span&gt;New in TensorFlow 2.4&lt;span&gt;&amp;nbsp;&lt;/span&gt;The argument&lt;span&gt;&amp;nbsp;&lt;/span&gt;save_traces&lt;span&gt;&amp;nbsp;&lt;/span&gt;has been added to&lt;span&gt;&amp;nbsp;&lt;/span&gt;model.save, which allows you to toggle SavedModel function tracing. Functions are saved to allow the Keras to re-load custom objects without the original class definitions, so when&lt;span&gt;&amp;nbsp;&lt;/span&gt;save_traces=False, all custom objects must have defined&lt;span&gt;&amp;nbsp;&lt;/span&gt;get_config/from_config&lt;span&gt;&amp;nbsp;&lt;/span&gt;methods. When loading, the custom objects must be passed to the&lt;span&gt;&amp;nbsp;&lt;/span&gt;custom_objects&lt;span&gt;&amp;nbsp;&lt;/span&gt;argument.&lt;span&gt;&amp;nbsp;&lt;/span&gt;save_traces=False&lt;span&gt;&amp;nbsp;&lt;/span&gt;reduces the disk space used by the SavedModel and saving time.&lt;br /&gt;&lt;a href=&quot;https://keras.io/guides/serialization_and_saving/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://keras.io/guides/serialization_and_saving/&lt;/a&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;내용은 요약하면, Tensorflow 2.4 이후 부터 &quot;model.save&quot; 할 때, get_config/from_config method가 정의되어 있어야 한다는 내용이다. (&quot;save_traces=False&quot;)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 찾아보니, Training 할 때도 자동으로 save가 되는 경우를 하나 발견했다.&amp;nbsp; 답은...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ModelCheckpoint&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 해결책은 2가지로 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) ModelCheckPoint 사용을 중지한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) get_config함수를 구현해 준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;해결방안 1) Model Check Point 제거&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ModelCheckPoint는 fit 함수 적용 시 checkPoint를 제외해 주면 되므로 간단한다. (대신 CheckPoint 저장이 되지 않을 것이다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 Fit()함수가 다음과 같은 형태를 취하고 있다고 가정하면,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657889324044&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;history = fc_model.fit( X_train , y_train , batch_size = 32, epochs=nEpochs, 
                       validation_data=(X_test, y_test), callbacks=[checkpointer] )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 checkpointer를 제거해 주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657889420547&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;history = fc_model.fit( X_train , y_train , batch_size = 32, epochs=nEpochs, 
                       validation_data=(X_test, y_test))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;해결방안 2) get_config() 메소드 구현&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 방법은 Custome 모델이 제대로 저장될 수 있도록 get_config()를 구현해주는 방법이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 Keras공식 문서에서 제공하는 Custom Model 저장을 지원하는 Class 구현이다.&amp;nbsp; &lt;b&gt;&quot;get_config()&quot;&lt;/b&gt; 주목하도록 하자.&lt;/p&gt;
&lt;pre id=&quot;code_1657889560388&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class CustomModel(keras.Model):
    def __init__(self, hidden_units):
        super(CustomModel, self).__init__()
        self.hidden_units = hidden_units
        self.dense_layers = [keras.layers.Dense(u) for u in hidden_units]

    def call(self, inputs):
        x = inputs
        for layer in self.dense_layers:
            x = layer(x)
        return x

    def get_config(self):
        return {&quot;hidden_units&quot;: self.hidden_units}

    @classmethod
    def from_config(cls, config):
        return cls(**config)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;참조 : https://keras.io/guides/serialization_and_saving/&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;get_config()는 저장하고자 하는 노드의 값을 Dictionary형태로 반환해 주도록 구현해 주면 된다. 상기의 예제에서는 hidden_units의 파라미터만 저장하고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 아래와 같이 모델에서 사용하는 모든 변수를 다 정의해 주었다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657889469975&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def get_config(self):
        config = {
            'rateDropout' : self.rateDropout,
            'conv_block1': self.conv_block1,
            'conv_block2': self.conv_block2,
            'conv_block3': self.conv_block3,
            'conv_block4': self.conv_block4,
            'conv_block5': self.conv_block5,
            'conv_block6': self.conv_block6,
            'fc1': self.fc1,
        }
        return config&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/200</guid>
      <comments>https://windflex.tistory.com/200#entry200comment</comments>
      <pubDate>Fri, 15 Jul 2022 22:02:52 +0900</pubDate>
    </item>
    <item>
      <title>[AWS 교육 요약] Developing on AWS (2/3)</title>
      <link>https://windflex.tistory.com/199</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkZ7tH/btrHfneAYQl/FLXEUGoSRuKVJKddvBaM3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkZ7tH/btrHfneAYQl/FLXEUGoSRuKVJKddvBaM3k/img.png&quot; data-alt=&quot;AWS CLI / SDK 활용하여 개발 환경 구축, 애플리케이션 개발&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkZ7tH/btrHfneAYQl/FLXEUGoSRuKVJKddvBaM3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkZ7tH%2FbtrHfneAYQl%2FFLXEUGoSRuKVJKddvBaM3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;358&quot; height=&quot;215&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;174&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS CLI / SDK 활용하여 개발 환경 구축, 애플리케이션 개발&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[관련글]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/197&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.07.11 - [IT 이야기/IT 상식] - AWS교육[요약]-Technical Essential : IAM/Role/EC2/VPC/ELB&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/198&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.07.13 - [개발 이야기] - [AWS 교육 요약] - Developing on AWS (1/4)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/199&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.07.13 - [개발 이야기] - [AWS 교육 요약] Developing on AWS (2/4)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS 데이터베이스 - DynamoDB&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1552&quot; data-origin-height=&quot;626&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXfG6D/btrG8JjlnO9/t4yK99rq9k6Ldorkin9TUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXfG6D/btrG8JjlnO9/t4yK99rq9k6Ldorkin9TUK/img.png&quot; data-alt=&quot;AWS 데이터베이스 서비스&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXfG6D/btrG8JjlnO9/t4yK99rq9k6Ldorkin9TUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXfG6D%2FbtrG8JjlnO9%2Ft4yK99rq9k6Ldorkin9TUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;634&quot; height=&quot;256&quot; data-origin-width=&quot;1552&quot; data-origin-height=&quot;626&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS 데이터베이스 서비스&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cf4Gfw/btrHbTY3gQm/olNL7TK6sbUZS9d7wOLKe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cf4Gfw/btrHbTY3gQm/olNL7TK6sbUZS9d7wOLKe1/img.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;546&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.4126%; margin-right: 10px;&quot; data-widthpercent=&quot;54.04&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cf4Gfw/btrHbTY3gQm/olNL7TK6sbUZS9d7wOLKe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcf4Gfw%2FbtrHbTY3gQm%2FolNL7TK6sbUZS9d7wOLKe1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1344&quot; height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ukOhj/btrG8tgLfPP/HpaXqqcMDEUcukHHhbeqgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ukOhj/btrG8tgLfPP/HpaXqqcMDEUcukHHhbeqgk/img.png&quot; data-origin-width=&quot;1524&quot; data-origin-height=&quot;728&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;45.96&quot; style=&quot;width: 45.4246%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ukOhj/btrG8tgLfPP/HpaXqqcMDEUcukHHhbeqgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FukOhj%2FbtrG8tgLfPP%2FHpaXqqcMDEUcukHHhbeqgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1524&quot; height=&quot;728&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;&amp;nbsp;관계형 데이터베이스 (RDB)와 비관계형 데이터베이스 비교 (좌), SQL/NoSQL 문서의 비교&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ Amazon DynamoDB ]&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;규모에 따른 성능&lt;/li&gt;
&lt;li&gt;엔터프라이즈에 사용 가능&lt;/li&gt;
&lt;li&gt;대기 시간이 짧은 쿼리&lt;/li&gt;
&lt;li&gt;서버리스 / 완전관리형&lt;/li&gt;
&lt;li&gt;세분화된 엑세스 제어&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;717&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Pq1ci/btrG8tnxd0G/PkMKCBiQcRzla9GvxjlG7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Pq1ci/btrG8tnxd0G/PkMKCBiQcRzla9GvxjlG7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Pq1ci/btrG8tnxd0G/PkMKCBiQcRzla9GvxjlG7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPq1ci%2FbtrG8tnxd0G%2FPkMKCBiQcRzla9GvxjlG7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1590&quot; height=&quot;717&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;717&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;DynamoDB는 파티션키를 필수로 요구한다. 왜 그럴까 생각해 보면, NoSQL DB관점에서 각 아이템(행)을 저장할 때 Hash를 사용하는데, Hash의 입력값으로 사용할 키가 필요하다. 이것이 기본적으로는 파티션키이다. 이러한 이유로 파티션키를 해시 속성이라고도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;만약 파티션키 만으로 고유값이 정해지지 않는다면, Secondary로 정렬키를 추가 설정 할 수 있다. 이 경우, Hash의 입력은 파티션키+정렬키가 된다. Sencondary Key가 정렬키라고 부르는 이유는, 파티션키값이 동일한 모든 항목을 물리적으로 서로 가까이 저장하도록 정의할 수 있으며, 이 때 정렬 기준으로 사용하기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;DynamoDB 개발/사용의 도구&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1)&amp;nbsp;NoSQL Workbench&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Cross-platform 클라이언트 GUI 애플리케이션&lt;/li&gt;
&lt;li&gt;데이터 모델링, 시각화, 작업 빌더&lt;/li&gt;
&lt;li&gt;PartiQL 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) DynamoDB Local&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터넷 연결 없이 로컬에 설치하여, aws cli로 접근&lt;/li&gt;
&lt;li&gt;처리량, 데이터 스토리지 및 데이터 전송 비용 절감&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMRnUk/btrHaok2Eer/3wbd9lUijRtqkRjEILjrEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMRnUk/btrHaok2Eer/3wbd9lUijRtqkRjEILjrEK/img.png&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;582&quot; data-is-animation=&quot;false&quot; style=&quot;width: 18.7948%; margin-right: 10px;&quot; data-widthpercent=&quot;19.02&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMRnUk/btrHaok2Eer/3wbd9lUijRtqkRjEILjrEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMRnUk%2FbtrHaok2Eer%2F3wbd9lUijRtqkRjEILjrEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;502&quot; height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uyQYo/btrG8sB8gDi/6l3C8jf6uyB9jlKTraY6OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uyQYo/btrG8sB8gDi/6l3C8jf6uyB9jlKTraY6OK/img.png&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;398&quot; data-is-animation=&quot;false&quot; style=&quot;width: 80.0424%;&quot; data-widthpercent=&quot;80.98&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uyQYo/btrG8sB8gDi/6l3C8jf6uyB9jlKTraY6OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuyQYo%2FbtrG8sB8gDi%2F6l3C8jf6uyB9jlKTraY6OK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1462&quot; height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;NoSQL Workbench (좌), Local DynamoDB 사용 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;[ DynamoDB에 대한 SDK/API&amp;nbsp; ]&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOQxW3/btrG9l97Art/x7E9Y1BdYZpk0VNRAh8fNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOQxW3/btrG9l97Art/x7E9Y1BdYZpk0VNRAh8fNK/img.png&quot; data-alt=&quot;python SDK (boto3)를 이용한 테이블 생성의 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOQxW3/btrG9l97Art/x7E9Y1BdYZpk0VNRAh8fNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOQxW3%2FbtrG9l97Art%2Fx7E9Y1BdYZpk0VNRAh8fNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1258&quot; height=&quot;562&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;python SDK (boto3)를 이용한 테이블 생성의 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0v28l/btrHaYsNtvT/HN51tyi55LK6ur6Ke74yN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0v28l/btrHaYsNtvT/HN51tyi55LK6ur6Ke74yN1/img.png&quot; data-origin-width=&quot;1562&quot; data-origin-height=&quot;682&quot; data-is-animation=&quot;false&quot; style=&quot;width: 44.5145%; margin-right: 10px;&quot; data-widthpercent=&quot;45.04&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0v28l/btrHaYsNtvT/HN51tyi55LK6ur6Ke74yN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0v28l%2FbtrHaYsNtvT%2FHN51tyi55LK6ur6Ke74yN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1562&quot; height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0dPuJ/btrHapKX96I/yRi3cSnwAGGjoVkHX1lwC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0dPuJ/btrHapKX96I/yRi3cSnwAGGjoVkHX1lwC0/img.png&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;556&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;54.96&quot; style=&quot;width: 54.3227%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0dPuJ/btrHapKX96I/yRi3cSnwAGGjoVkHX1lwC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0dPuJ%2FbtrHapKX96I%2FyRi3cSnwAGGjoVkHX1lwC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1554&quot; height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;GetItem을 POST로 전송하는 HTTP Request 전문 (좌), Response 전문 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;[ DB 제어 ]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제어 (DML) : Create, Update, Delete, List, Describe&lt;/li&gt;
&lt;li&gt;데이터 영역 : &lt;span&gt;CRUD&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;Put, Update, Get, Delete)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;[ DB 설계 ]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;파티션키/정렬키의 설계에 따라서 &quot;질의&quot;가 아닌 &quot;스캐닝&quot;이 되어 버릴 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아래 예의 경우, 좌측은 NoteId를 파티션키로, 우측은 UserID를 파티션 키 (+ 정렬키)로 생서하였다. 이 경우 만약 UserID==&quot;StudentC&quot;인 조건으로 검색을 한다면,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;좌측의 설계는 StudentC를 조회하기 위해서 전체 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&quot;스캔&quot;&lt;/span&gt;이 발생함&lt;/li&gt;
&lt;li&gt;우측은 UserID가 파티션 키로 설정 되었기 때문에 --&amp;gt; Indexing이 UserID로 생성되었고 --&amp;gt; Hash( key )로 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;&quot;질.의&quot;&lt;/b&gt;&lt;/span&gt;가 된다.&lt;/li&gt;
&lt;li&gt;파티션키와 정렬키 외에 검색/질의를 하기 위해서는 보조인덱스를 사용하여, 인덱싱 --&amp;gt; 질의 하는 방법을 사용할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSYOC9/btrHcLzNK0n/foJYuiEiWRhuUR9mdUTDH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSYOC9/btrHcLzNK0n/foJYuiEiWRhuUR9mdUTDH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSYOC9/btrHcLzNK0n/foJYuiEiWRhuUR9mdUTDH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSYOC9%2FbtrHcLzNK0n%2FfoJYuiEiWRhuUR9mdUTDH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1556&quot; height=&quot;436&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Python SDK - DynamoDB (Pratice-03)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;[ 실습 목표 ]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램 (하위수준 API, 상위수준 API)을 사용하여, DynamoDB 제어&lt;/li&gt;
&lt;li&gt;파티션키, 정렬키 --&amp;gt; Waiter를 사용 --&amp;gt; 테이블 생성&lt;/li&gt;
&lt;li&gt;파일에서 JSON 객체 Read, Table Load&lt;/li&gt;
&lt;li&gt;Search (Key, Filter, Array) / Update&lt;/li&gt;
&lt;li&gt;PartiQL을 사용하여 DynamoDB 데이터 엑세스&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxzw8m/btrG9kQSOEq/tCWMy9VB5tYfqnl4ZQNaFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxzw8m/btrG9kQSOEq/tCWMy9VB5tYfqnl4ZQNaFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxzw8m/btrG9kQSOEq/tCWMy9VB5tYfqnl4ZQNaFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbxzw8m%2FbtrG9kQSOEq%2FtCWMy9VB5tYfqnl4ZQNaFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;287&quot; height=&quot;231&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Python DynamoDB SDK :&amp;nbsp;https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;[ 항목 읽기 ]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;aws dynamodb get-item --table-name Notes --key '{&quot;UserId&quot;:{&quot;S&quot;: &quot;StudentA&quot;}, &quot;NoteId&quot;:{&quot;N&quot;: &quot;11&quot;} }'&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/whi5G/btrG8HF8sxq/i9xqD2BscQcaLOKsHmKw11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/whi5G/btrG8HF8sxq/i9xqD2BscQcaLOKsHmKw11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/whi5G/btrG8HF8sxq/i9xqD2BscQcaLOKsHmKw11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwhi5G%2FbtrG8HF8sxq%2Fi9xqD2BscQcaLOKsHmKw11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1554&quot; height=&quot;620&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;[ 쿼리 질의 하기 ]&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1146&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ps9F7/btrHdwvQyYk/mwMZFnYByxMeYiQ161L8oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ps9F7/btrHdwvQyYk/mwMZFnYByxMeYiQ161L8oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ps9F7/btrHdwvQyYk/mwMZFnYByxMeYiQ161L8oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fps9F7%2FbtrHdwvQyYk%2FmwMZFnYByxMeYiQ161L8oK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1146&quot; height=&quot;220&quot; data-origin-width=&quot;1146&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;스캔 (Scan)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1146&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WdBIh/btrHbUKMujz/sBumKCifx9y6CQH4x08H7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WdBIh/btrHbUKMujz/sBumKCifx9y6CQH4x08H7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WdBIh/btrHbUKMujz/sBumKCifx9y6CQH4x08H7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWdBIh%2FbtrHbUKMujz%2FsBumKCifx9y6CQH4x08H7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1146&quot; height=&quot;220&quot; data-origin-width=&quot;1146&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;업데이트&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d22ngA/btrG8QQbzj8/v6fxzHXP3qE8WJ25t4xGx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d22ngA/btrG8QQbzj8/v6fxzHXP3qE8WJ25t4xGx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d22ngA/btrG8QQbzj8/v6fxzHXP3qE8WJ25t4xGx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd22ngA%2FbtrG8QQbzj8%2Fv6fxzHXP3qE8WJ25t4xGx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1554&quot; height=&quot;564&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ 조건부 쓰기 작업 ]&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xsv1a/btrHaY0ZPJu/8AvNVrb5EFNStbcS4tQDBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xsv1a/btrHaY0ZPJu/8AvNVrb5EFNStbcS4tQDBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xsv1a/btrHaY0ZPJu/8AvNVrb5EFNStbcS4tQDBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxsv1a%2FbtrHaY0ZPJu%2F8AvNVrb5EFNStbcS4tQDBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1596&quot; height=&quot;664&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ 항목 삭제 ]&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbqIio/btrG8ngHWXN/rsYTN0BICjoyt6JnGgwqCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbqIio/btrG8ngHWXN/rsYTN0BICjoyt6JnGgwqCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbqIio/btrG8ngHWXN/rsYTN0BICjoyt6JnGgwqCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbqIio%2FbtrG8ngHWXN%2FrsYTN0BICjoyt6JnGgwqCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1596&quot; height=&quot;596&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Python SDK 활용 DynamoDB 제어 (Practice-03)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFJQ5w/btrHaX198PM/1xGRq28uYbwPl30PvR8Kok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFJQ5w/btrHaX198PM/1xGRq28uYbwPl30PvR8Kok/img.png&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;346&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.783%; margin-right: 10px;&quot; data-widthpercent=&quot;52.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFJQ5w/btrHaX198PM/1xGRq28uYbwPl30PvR8Kok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFJQ5w%2FbtrHaX198PM%2F1xGRq28uYbwPl30PvR8Kok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;687&quot; height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIp7hM/btrHdaGGzpQ/lIbYfFT04EoSlx8QZ8pIZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIp7hM/btrHdaGGzpQ/lIbYfFT04EoSlx8QZ8pIZK/img.png&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;378&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.0542%;&quot; data-widthpercent=&quot;47.61&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIp7hM/btrHdaGGzpQ/lIbYfFT04EoSlx8QZ8pIZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIp7hM%2FbtrHdaGGzpQ%2FlIbYfFT04EoSlx8QZ8pIZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;682&quot; height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS Web Console에서 DynamoDB 초기 화면 (좌). 테이블 항목이 없음 확인. Cloud9 기본 설정(ini파일)되어 있는 개발 환경 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;첫번째 주어진 미션은 &quot;DynamoDB 테이블을 생성&quot;하는 것.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 위해서,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DynamoDB 개체를 생성&lt;/li&gt;
&lt;li&gt;Table Creation&lt;/li&gt;
&lt;li&gt;Wait unti table exists&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ 설정파일 (config.ini) ]&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1657689931398&quot; class=&quot;ini&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[DynamoDB]
tableName = Notes
partitionKey = UserId
sortKey = NoteId
readCapacity = 5
writeCapacity = 5
sourcenotes = ./labRepo/notes.json
queryUserId = student
pageSize = 3
queryNoteId = 5
notePrefix = The maximum item size in DynamoDB is&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설정 파일 처리 (config.ini) - configparser&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1657691259056&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import configparser
def readConfig():
    config = configparser.ConfigParser()
    config.read('./labRepo/config.ini')

    return config['DynamoDB']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ Dynamo DB 개체 생성 ]&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1657687049357&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;client = boto3.client('dynamodb')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[Dynamo DB Table Create]&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1657687109505&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    response = ddbClient.create_table(
        AttributeDefinitions=[
            {
                'AttributeName': tableDefinition[&quot;partitionKey&quot;],
                'AttributeType': 'S',
            },
            {
                'AttributeName': tableDefinition[&quot;sortKey&quot;],
                'AttributeType': 'N',
            },
        ],
        KeySchema=[
            {
                'AttributeName': tableDefinition[&quot;partitionKey&quot;],
                'KeyType': 'HASH',
            },
            {
                'AttributeName': tableDefinition[&quot;sortKey&quot;],
                'KeyType': 'RANGE',
            },
        ],
        ProvisionedThroughput={
            'ReadCapacityUnits': int(tableDefinition[&quot;readCapacity&quot;]),
            'WriteCapacityUnits': int(tableDefinition[&quot;writeCapacity&quot;]),
        },
        TableName=tableDefinition[&quot;tableName&quot;]
    )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ Wait until Exists ]&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1657687133357&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;waiter = ddbClient.get_waiter('table_exists')
waiter.wait( TableName=tableName )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eu4ui0/btrHdaGMDCM/j7WipKautAJCad68kcoukk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eu4ui0/btrHdaGMDCM/j7WipKautAJCad68kcoukk/img.png&quot; data-origin-width=&quot;417&quot; data-origin-height=&quot;166&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.1182%; margin-right: 10px;&quot; data-widthpercent=&quot;48.68&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eu4ui0/btrHdaGMDCM/j7WipKautAJCad68kcoukk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feu4ui0%2FbtrHdaGMDCM%2Fj7WipKautAJCad68kcoukk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;417&quot; height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qYNCu/btrHapSdq3I/hpNBpRpOYG7gpl81KKSeRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qYNCu/btrHapSdq3I/hpNBpRpOYG7gpl81KKSeRK/img.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;230&quot; data-is-animation=&quot;false&quot; style=&quot;width: 50.719%;&quot; data-widthpercent=&quot;51.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qYNCu/btrHapSdq3I/hpNBpRpOYG7gpl81KKSeRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqYNCu%2FbtrHapSdq3I%2FhpNBpRpOYG7gpl81KKSeRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;609&quot; height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Python Code를 완성 후 실행하면 DynamoDB Table이 생성된다. (좌), Web Console에서 확인하면 처음과 달리 &quot;Notes&quot;라는 Table이 생성되어 있다. (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ 데이터 입력 ]&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Table은 생성했으나 아직은 어떠한 데이터/아이템도 입력하지 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 데이터 아이템을 입력해 보자. 이때 위에서 정의한 PartitionKey와 SortKey는 모두 포함되어야 한다. 즉, PartitionKey인 &quot;UserId&quot; 또는 sortKey인 &quot;NoteId&quot;를 생략하면 안된다는 이야기이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 note가 주어질 때 table에 데이터를 입력하는 함수이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657687847417&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def putNote(table, note):
    print(&quot;loading note &quot; + str(note))
   
    table.put_item(
        Item={
            'UserId': note[&quot;UserId&quot;],
            'NoteId': int(note[&quot;NoteId&quot;]),
            'Note': note[&quot;Note&quot;]
        }
    )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;putNote함수와 JSON 파일을 이용하여 아래와 같이 Item을 입력할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657688185171&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    f = open(jsonFileName)

    print(&quot;\n Loading \&quot;&quot; + tableName +
        &quot;\&quot; table with data from file \&quot;&quot; + jsonFileName + &quot;\&quot;\n\n&quot;)
    # Load json object from file
    notes = json.load(f)

    # Create dynamodb table resource
    table = ddbResource.Table(tableName)

    # Iterating through the notes and putting them in the table
    for n in notes:
        putNote(table, n)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dgdbID/btrHcKIcSM3/YE6MBU8VEL0r6Xy7gmCZt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dgdbID/btrHcKIcSM3/YE6MBU8VEL0r6Xy7gmCZt1/img.png&quot; width=&quot;387&quot; height=&quot;136&quot; data-origin-width=&quot;315&quot; data-origin-height=&quot;182&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;51.1&quot; data-filename=&quot;blob&quot; style=&quot;width: 50.5096%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dgdbID/btrHcKIcSM3/YE6MBU8VEL0r6Xy7gmCZt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdgdbID%2FbtrHcKIcSM3%2FYE6MBU8VEL0r6Xy7gmCZt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;315&quot; height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cphqXU/btrHdtlTfj0/MLpafIkJ3gzGhJcQeE55WK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cphqXU/btrHdtlTfj0/MLpafIkJ3gzGhJcQeE55WK/img.png&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;375&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;48.9&quot; style=&quot;width: 48.3276%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cphqXU/btrHdtlTfj0/MLpafIkJ3gzGhJcQeE55WK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcphqXU%2FbtrHdtlTfj0%2FMLpafIkJ3gzGhJcQeE55WK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;621&quot; height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Table의 초기 상태. 아이템이 없다 (좌), JSON파일로부터 Table에 Item을 입력 후 상태 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ 데이터 쿼리 by PartitionKey ]&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657688571333&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def main(ddbClient):
    
    ##load configuration data from file
    config = readConfig()

    tableName = config['tableName']
    UserId = config['queryUserId']

    print(&quot;\n************\nQuerying for notes that belong to user &quot; + UserId + &quot;...\n&quot;)
    printNotes(queryNotesByPartitionKey(ddbClient, tableName, UserId))

def queryNotesByPartitionKey(ddbClient, tableName, qUserId):

    response = ddbClient.query(
        TableName=tableName,
        KeyConditionExpression='UserId = :userId',
        ExpressionAttributeValues={
            ':userId': {&quot;S&quot;: qUserId}
        },
        ProjectionExpression=&quot;NoteId, Note&quot;
    )

    return response[&quot;Items&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과&lt;/p&gt;
&lt;pre id=&quot;code_1657688729934&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{&quot;Note&quot;: &quot;DynamoDB is NoSQL&quot;, &quot;NoteId&quot;: &quot;1&quot;}
{&quot;Note&quot;: &quot;A DynamoDB table is schemaless&quot;, &quot;NoteId&quot;: &quot;2&quot;}
{&quot;Note&quot;: &quot;PartiQL is a SQL compatible language for DynamoDB&quot;, &quot;NoteId&quot;: &quot;3&quot;}
{&quot;Note&quot;: &quot;I love DyDB&quot;, &quot;NoteId&quot;: &quot;4&quot;}
{&quot;Note&quot;: &quot;Maximum size of an item is ____ KB ?&quot;, &quot;NoteId&quot;: &quot;5&quot;}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&amp;nbsp;[ 스캔 / 페이지네이트 ]&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657688901689&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def main(ddbClient):
    ##load configuration data from file
    config = readConfig()
    tableName = config['tableName']
    pageSize = config['pageSize']
    print(&quot;\n************\nScanning with pagination...\n&quot;)
    queryAllNotesPaginator(ddbClient, tableName, pageSize)

def queryAllNotesPaginator(ddbClient, tableName, pageSize):
	paginator = ddbClient.get_paginator('scan')

    page_iterator = paginator.paginate(
        TableName=tableName,
        PaginationConfig={
            'PageSize': pageSize
        })

    pageNumber = 0
    for page in page_iterator:
        if page[&quot;Count&quot;] &amp;gt; 0:
            pageNumber += 1
            print(&quot;Starting page &quot; + str(pageNumber))
            printNotes(page['Items'])
            print(&quot;End of page &quot; + str(pageNumber) + &quot;\n&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과 : 페이지 사이즈 (==&amp;gt;3)으로 나누어서 출력되는 것을 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657689023703&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Starting page 1
{&quot;Note&quot;: &quot;hello&quot;, &quot;UserId&quot;: &quot;testuser&quot;, &quot;NoteId&quot;: &quot;1&quot;}
{&quot;Note&quot;: &quot;this is my first note&quot;, &quot;UserId&quot;: &quot;testuser&quot;, &quot;NoteId&quot;: &quot;2&quot;}
{&quot;Note&quot;: &quot;DynamoDB is NoSQL&quot;, &quot;UserId&quot;: &quot;student&quot;, &quot;NoteId&quot;: &quot;1&quot;}
End of page 1

Starting page 2
{&quot;Note&quot;: &quot;A DynamoDB table is schemaless&quot;, &quot;UserId&quot;: &quot;student&quot;, &quot;NoteId&quot;: &quot;2&quot;}
{&quot;Note&quot;: &quot;PartiQL is a SQL compatible language for DynamoDB&quot;, &quot;UserId&quot;: &quot;student&quot;, &quot;NoteId&quot;: &quot;3&quot;}
{&quot;Note&quot;: &quot;I love DyDB&quot;, &quot;UserId&quot;: &quot;student&quot;, &quot;NoteId&quot;: &quot;4&quot;}
End of page 2

Starting page 3
{&quot;Note&quot;: &quot;Maximum size of an item is ____ KB ?&quot;, &quot;UserId&quot;: &quot;student&quot;, &quot;NoteId&quot;: &quot;5&quot;}
{&quot;Note&quot;: &quot;Free swag code: 1234&quot;, &quot;UserId&quot;: &quot;newbie&quot;, &quot;NoteId&quot;: &quot;1&quot;}
{&quot;Note&quot;: &quot;I love DynamoDB&quot;, &quot;UserId&quot;: &quot;newbie&quot;, &quot;NoteId&quot;: &quot;2&quot;}
End of page 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ 업데이트 ]&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657689433388&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def main(ddbClient):  
    config = readConfig()
    tableName = config['tableName']
    qUserId = config['queryUserId']
    qNoteId = config['queryNoteId']
    notePrefix = config['notePrefix']
    
    print(&quot;\nUpdating the note flag for remediation...\n&quot;)
    print(updateNewAttribute(ddbClient, tableName, qUserId, qNoteId))

    print(&quot;\nRemediating the marked note...\n&quot;)
    print(updateExistingAttributeConditionally(ddbClient, tableName, qUserId, qNoteId, notePrefix))


def updateNewAttribute(ddbClient, tableName, qUserId, qNoteId):
    response = ddbClient.update_item(
        TableName=tableName,
        Key={
            'UserId': {'S': qUserId},
            'NoteId': {'N': str(qNoteId)}
        },
        ReturnValues='ALL_NEW',
        UpdateExpression='SET Is_Incomplete = :incomplete',
        ExpressionAttributeValues={
            ':incomplete': {'S': 'Yes'}
        }
    )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컬럼이 추가 되었음을 확인 할수 잇다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q21dS/btrHdJIS6n4/OX7QFu4KipoJxKG91HUNJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q21dS/btrHdJIS6n4/OX7QFu4KipoJxKG91HUNJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q21dS/btrHdJIS6n4/OX7QFu4KipoJxKG91HUNJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq21dS%2FbtrHdJIS6n4%2FOX7QFu4KipoJxKG91HUNJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;641&quot; height=&quot;456&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[ PartiQL 을 사용하여 질의 ]&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1657689676884&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def main(ddbClient):
    config = readConfig()
    tableName = config['tableName']
    UserId = config['queryUserId']
    NoteId = config['queryNoteId']
    print(&quot;\n************\nQuerying for note &quot; + str(NoteId) + &quot; that belongs to user &quot; + UserId + &quot;...\n&quot;)
    printNotes(querySpecificNote(ddbClient, tableName, UserId, NoteId))

def querySpecificNote(ddbClient, tableName, qUserId, qNoteId):
    response = ddbClient.execute_statement(
        Statement=&quot;SELECT * FROM &quot; + tableName + &quot; WHERE UserId = ? AND NoteId = ?&quot;,
        Parameters=[
            {&quot;S&quot;: qUserId},
            {&quot;N&quot;: str(qNoteId)}
        ]
    )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;서버리스 (Serverless )&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsEIR8/btrHapylQta/zyPAbjrmUq2kpvPjUHPhEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsEIR8/btrHapylQta/zyPAbjrmUq2kpvPjUHPhEk/img.png&quot; data-origin-width=&quot;1484&quot; data-origin-height=&quot;564&quot; data-is-animation=&quot;false&quot; style=&quot;width: 52.7155%; margin-right: 10px;&quot; data-widthpercent=&quot;53.34&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsEIR8/btrHapylQta/zyPAbjrmUq2kpvPjUHPhEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsEIR8%2FbtrHapylQta%2FzyPAbjrmUq2kpvPjUHPhEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1484&quot; height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PkwVi/btrG8XCwVMR/m8sovYd1m8o0rBMGKlkSUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PkwVi/btrG8XCwVMR/m8sovYd1m8o0rBMGKlkSUK/img.png&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;576&quot; data-is-animation=&quot;false&quot; width=&quot;614&quot; height=&quot;267&quot; style=&quot;width: 46.1217%;&quot; data-widthpercent=&quot;46.66&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PkwVi/btrG8XCwVMR/m8sovYd1m8o0rBMGKlkSUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPkwVi%2FbtrG8XCwVMR%2Fm8sovYd1m8o0rBMGKlkSUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1326&quot; height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS Lambda 함수의 구조 (좌), AWS Lambda의 활용 개요도 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS의 컴퓨팅 서비스 의 추상화 수준&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상화 정도 : EC2 인스턴스 --&amp;gt; 컨테이너 (ECS, EKS) --&amp;gt; 서버리스 (AWS Lambda)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS Lambda 호출 방법&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1512&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cb7zhQ/btrG9kxws3C/Xzk2PhZ4dClKt4iew649q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cb7zhQ/btrG9kxws3C/Xzk2PhZ4dClKt4iew649q1/img.png&quot; data-alt=&quot;AWS Lambda 호출 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cb7zhQ/btrG9kxws3C/Xzk2PhZ4dClKt4iew649q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcb7zhQ%2FbtrG9kxws3C%2FXzk2PhZ4dClKt4iew649q1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;544&quot; height=&quot;239&quot; data-origin-width=&quot;1512&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS Lambda 호출 방법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동기식 (직접 호출)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS CLI 도는 SDK에서 직접 호출하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push방식/이벤트 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 특정 Bucket에 데이터가 들어오면 Lambda 호출하도록 Trigger 등록&lt;/li&gt;
&lt;li&gt;Bucket쪽에서 Lambda 함수를 호출&lt;/li&gt;
&lt;li&gt;당연하게도, Bucket에 Lambda를 호출할 수 있는 권한이 있어야함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pull 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) Lambda가 10초에 한번씩&amp;nbsp; DynamoDB의 변경정보 여부 점검&lt;/li&gt;
&lt;li&gt;Lambda 함수에서 DynamoDB를 사용할 수 있는 권한이 있어야함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1548&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcQAwi/btrHdxhSXwl/2h6Z6ARKFInR9ai3gTdUCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcQAwi/btrHdxhSXwl/2h6Z6ARKFInR9ai3gTdUCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcQAwi/btrHdxhSXwl/2h6Z6ARKFInR9ai3gTdUCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcQAwi%2FbtrHdxhSXwl%2F2h6Z6ARKFInR9ai3gTdUCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1548&quot; height=&quot;676&quot; data-origin-width=&quot;1548&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;API Gateway&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nAGjd/btrG9kK6XlS/rg8zxQFHeGKaoNMkubaKy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nAGjd/btrG9kK6XlS/rg8zxQFHeGKaoNMkubaKy1/img.png&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;740&quot; data-is-animation=&quot;false&quot; width=&quot;646&quot; height=&quot;305&quot; style=&quot;width: 48.0486%; margin-right: 10px;&quot; data-widthpercent=&quot;48.61&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nAGjd/btrG9kK6XlS/rg8zxQFHeGKaoNMkubaKy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnAGjd%2FbtrG9kK6XlS%2Frg8zxQFHeGKaoNMkubaKy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1568&quot; height=&quot;740&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k26aE/btrG9TT0bPs/jdrGbXRvtJUi9zFhXKtNzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k26aE/btrG9TT0bPs/jdrGbXRvtJUi9zFhXKtNzk/img.png&quot; data-origin-width=&quot;1420&quot; data-origin-height=&quot;634&quot; data-is-animation=&quot;false&quot; style=&quot;width: 50.7886%;&quot; data-widthpercent=&quot;51.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k26aE/btrG9TT0bPs/jdrGbXRvtJUi9zFhXKtNzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk26aE%2FbtrG9TT0bPs%2FjdrGbXRvtJUi9zFhXKtNzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1420&quot; height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;API Gateway작동 방식 (좌), API Gateway의 개발자 기능 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS Lambda 사용한 솔루션 개발 (Practice-04)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 실습 목표 ]&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;- AWS Lambda 함수 생성&lt;br /&gt;&lt;span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;AWS SDK / CLI 사용하여 제어&lt;br /&gt;&lt;span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Lambda 함수를 구성하고 환경변수활용&lt;br /&gt;&lt;span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;AWS SDK -&amp;gt; 버킷 객체에 엑세스&lt;br /&gt;&lt;span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;AWS CLI 사용하여 AWS Lambda 함수 호출&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caIdkv/btrHeqh7yF1/GCRbcTkcodVS18csME6gJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caIdkv/btrHeqh7yF1/GCRbcTkcodVS18csME6gJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caIdkv/btrHeqh7yF1/GCRbcTkcodVS18csME6gJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaIdkv%2FbtrHeqh7yF1%2FGCRbcTkcodVS18csME6gJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;268&quot; height=&quot;258&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;856&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mZvXS/btrHdwRc2BI/aFRg58kneC0qHbkFek1JG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mZvXS/btrHdwRc2BI/aFRg58kneC0qHbkFek1JG1/img.png&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;351&quot; data-is-animation=&quot;false&quot; style=&quot;width: 62.6515%; margin-right: 10px;&quot; data-widthpercent=&quot;63.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mZvXS/btrHdwRc2BI/aFRg58kneC0qHbkFek1JG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmZvXS%2FbtrHdwRc2BI%2FaFRg58kneC0qHbkFek1JG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;816&quot; height=&quot;351&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AqbvM/btrHcKIUpHc/ORmyWaRnTzdgez5Zbs1KM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AqbvM/btrHcKIUpHc/ORmyWaRnTzdgez5Zbs1KM0/img.png&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;674&quot; data-is-animation=&quot;false&quot; style=&quot;width: 36.1857%;&quot; data-widthpercent=&quot;36.61&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AqbvM/btrHcKIUpHc/ORmyWaRnTzdgez5Zbs1KM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAqbvM%2FbtrHcKIUpHc%2FORmyWaRnTzdgez5Zbs1KM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;905&quot; height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS Web Console &amp;gt; Lambda &amp;gt; Create Function (좌), Create Function 메뉴에서 설정할 항목들 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, AWS Web Console에서 Lambda 함수를 만들어 보자.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Service &amp;gt; Lambda &amp;gt; Create Function 버튼&lt;/li&gt;
&lt;li&gt;function Name : dictate-function&lt;/li&gt;
&lt;li&gt;Runtime : Python 3.9 (버전에 맞게 선택)&lt;/li&gt;
&lt;li&gt;Change default execution role &amp;gt; Use an existing role 선택 후, Existing Role에서 &quot;lambdaPollyRole&quot;선택&lt;/li&gt;
&lt;li&gt;Create Function 버튼 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 과정을 통하여 기본으로 생성된 Lambda_function은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;255&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bELLN5/btrHd0Rxgpe/hoTTaWCrl76TeqjVEkEWCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bELLN5/btrHd0Rxgpe/hoTTaWCrl76TeqjVEkEWCk/img.png&quot; data-alt=&quot;Lambda Function을 생성하면 확인할 수 있는 기본 handler 함수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bELLN5/btrHd0Rxgpe/hoTTaWCrl76TeqjVEkEWCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbELLN5%2FbtrHd0Rxgpe%2FhoTTaWCrl76TeqjVEkEWCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;658&quot; height=&quot;255&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;255&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Lambda Function을 생성하면 확인할 수 있는 기본 handler 함수&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;처음이므로 이해하기 쉽도록, Web Console을 사용하여 Lambda Function을 생성하였다. 그러나, AWS CLI / SDK를 사용하여 Lambda Function을 생성할 수도 있다. AWS CLI를 통한 Lambda Function Create는 본 포스팅의 후반부 쪽에서 다루도록 하겠다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 CLI를 통하여 Lambda를 제어 해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 자주 명령줄 내에 삽입될 버킷이름을 구하여, 변수로 저장해 놓도록 하자. 아래는 2가지 변수를 지정한다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;`aws s3api list-buckets` 저수준 api를 사용하여 s3 bucket 이름에 &quot;apibucket&quot; 포함된 버킷을 찾고, 버킷의 이름을 &quot;apiBucket&quot; 으로 저장한다.&lt;/li&gt;
&lt;li&gt;notesTable에는 테이블이름인 &quot;Notes&quot;를 저장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1657701540732&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiBucket=$(aws s3api list-buckets --output text --query 'Buckets[?contains(Name, `apibucket`) == `true`] | [0].Name')
notesTable='Notes'&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;실습 환경에는 이미 S3버킷이 생성되어 있다. 버킷의 이름은 qls-xxxxxx-xxxxxxxxxxxxxxx-pollynotesapibucket-xxxxxxxxxx 등의 형태로 이름이 지어져 있는데, &quot;xxxxxxx&quot;등의 수치는 그때 그때 변경 되므로 버킷이름을 찾기 위해서 번거롭지만 위와 같이 &quot;apibucket&quot; 문자열을 &quot;contains&quot; 하고 있는 개체를 찾는 과정을 수반한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[ Lambda Function Update ]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 Web Console에서 Lambda funtion을 이미 생성해 두었으므로, 생성 단계는 건너 뛴다. 일단 Lambda function의 설정을 업데이트 해보도록 한자. 다음은 Lambda Function의 환경 변수를 업데이트 한다. 앞서 확인한 버킷의 이름과 테이블 이름을 미리 업데이트 해준다. (참고로, Function을 생성할 때 environment Variables를 한꺼번에 입력할 수 있다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657702090220&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws lambda update-function-configuration \
--function-name dictate-function \
--environment Variables=&quot;{MP3_BUCKET_NAME=$apiBucket, TABLE_NAME=$notesTable}&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 실행하면 현재 Labmda Function의 설정 값들을 JSON으로 보여 준다. 여러 반환 값중 아래와 같이 환경변수가 설정 되어 있는 것을 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wagxd/btrHepKB3dj/AiE6oSqWCLKktQP6l2tca0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wagxd/btrHepKB3dj/AiE6oSqWCLKktQP6l2tca0/img.png&quot; data-alt=&quot;aws lambda update-function-configuration을 통한 환경변수 업데이트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wagxd/btrHepKB3dj/AiE6oSqWCLKktQP6l2tca0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWagxd%2FbtrHepKB3dj%2FAiE6oSqWCLKktQP6l2tca0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;592&quot; height=&quot;134&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;aws lambda update-function-configuration을 통한 환경변수 업데이트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lambda Function으로 업로드하고자 하는 대상&lt;/p&gt;
&lt;pre id=&quot;code_1657702778858&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from __future__ import print_function
import boto3
import os
from contextlib import closing

dynamoDBResource = boto3.resource('dynamodb')
pollyClient = boto3.client('polly') 
s3Client = boto3.client('s3')

def lambda_handler(event, context):
    UserId = event[&quot;UserId&quot;]
    NoteId = event[&quot;NoteId&quot;]
    VoiceId = event['VoiceId']
    mp3Bucket = os.environ['MP3_BUCKET_NAME']
    ddbTable = os.environ['TABLE_NAME']
    
    text = getNote(dynamoDBResource, ddbTable, UserId, NoteId)
    filePath = createMP3File(pollyClient, text, VoiceId, NoteId)
    signedURL = hostFileOnS3(s3Client, filePath, mp3Bucket, UserId, NoteId)
    
    return signedURL

def getNote(dynamoDBResource, ddbTable, UserId, NoteId):

    table = dynamoDBResource.Table(ddbTable)
    records = table.get_item(
        Key={
            'UserId': UserId,
            'NoteId': int(NoteId)
        }
    )
    return records['Item']['Note']

def createMP3File(pollyClient, text, VoiceId, NoteId):
    pollyResponse = pollyClient.synthesize_speech(
        OutputFormat='mp3',
        Text = text,
        VoiceId = VoiceId
    )

	if &quot;AudioStream&quot; in pollyResponse:
        postId = str(NoteId)
        with closing(pollyResponse[&quot;AudioStream&quot;]) as stream:
            filePath = os.path.join(&quot;/tmp/&quot;, postId)
            with open(filePath, &quot;wb&quot;) as file:
                file.write(stream.read())

    return filePath

def hostFileOnS3(s3Client, filePath, mp3Bucket, UserId, NoteId):
    s3Client.upload_file(filePath,
                        mp3Bucket,
                        UserId+'/'+NoteId+'.mp3')
    os.remove(filePath)

    url = s3Client.generate_presigned_url(
        ClientMethod='get_object',
        Params={
            'Bucket': mp3Bucket,
            'Key': UserId+'/'+NoteId+'.mp3'
        }
    )

    return url&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lambda function으로 업로드 할 때는, zip압축 파일 형태로 업로드 해야 한다. 따라서, 사용하고자 하는 함수 파일(ex. app.py)을 zip으로 압축하도록 하자.&lt;/p&gt;
&lt;pre id=&quot;code_1657702949363&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;zip dictate-function.zip app.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;압축된 파일을 이제 lambda function으로 업데이트 한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657702735732&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws lambda update-function-code \
--function-name dictate-function \
--zip-file fileb://dictate-function.zip&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;function-name은 윗 단계 AWS Console에서 생성한 Lambda Function/Layer의 이름이다. zip-file은 본인이 압축한 zip파일의 이름이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;function의 소스/압축파일은 업로드를 했지만, 아직 function이 동작해야하는 handler가 어디에 있는지 지정해 주지 않았다. configuare update를 통해 핸들러를 지정해 주자.&lt;/p&gt;
&lt;pre id=&quot;code_1657703181093&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws lambda update-function-configuration \
--function-name dictate-function \
--handler app.lambda_handler&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ Lambda Function 호출 ]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본인의 코드로 Lambda Function을 업데이트 완료 했다. 이제 실제 호출하여 정상 동작하는지 살펴볼 차례이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 Lambda Function을 호출할 때 입력값 데이터를 만들어 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1657703373711&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat &amp;gt; event.json
{
  &quot;UserId&quot;: &quot;newbie&quot;,
  &quot;NoteId&quot;: &quot;2&quot;,
  &quot;VoiceId&quot;: &quot;Joey&quot;
}
^C&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 `aws lambda invoke`를 사용하여 직접 호출 해 준다. 이 때, function-name으로 대상 (lambda function)을 지정해 주고, 입력값은 --payload 옵션으로 지정해 준다.&lt;/p&gt;
&lt;pre id=&quot;code_1657703255159&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws lambda invoke \
--function-name dictate-function \
--payload fileb://event.json outputs.txt&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;outputs.txt에는 Lambda Function -&amp;gt; handler의 결과 값이 반환 되어 있을 것이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[ Lambda Function 동작 결과 확인]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Lambda Function이 정상 동작 했다면, output.txt에 예상되는 결과가 기록 되어 있을 것이다.&lt;/li&gt;
&lt;li&gt;우리가 사용한 Lambda Function은 입력값이 들어올 때, 해당 조건에 매칭되는 Data Item을 DynamoDB 찾고, 메모 텍스트를 음성으로 읽어 (TTS : AWS Polly 서비스), MP3파일로 변환하여 S3 버킷에 저장하는 함수이다. 따라서, 실행 후 지정된 AWS Bucket에 MP3이 저장되어 있는지 확인해 보자.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYCc4W/btrG87E9qut/or1l08AXTJngd5K2UzPuL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYCc4W/btrG87E9qut/or1l08AXTJngd5K2UzPuL0/img.png&quot; data-alt=&quot;AWS Lambda 함수 실행을 통하여 자동 생성된 mp3파일이 S3 버킷에 저장되어 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYCc4W/btrG87E9qut/or1l08AXTJngd5K2UzPuL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYCc4W%2FbtrG87E9qut%2For1l08AXTJngd5K2UzPuL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;569&quot; height=&quot;170&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS Lambda 함수 실행을 통하여 자동 생성된 mp3파일이 S3 버킷에 저장되어 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ AWS Web Console에서 Lambda Function TEST ]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lambda Function에 대한 1회적인 실행/테스트는 웹 콘솔을 통해서 도 테스트 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS Service &amp;gt; Lambda &amp;gt; Functions &amp;gt; &quot;내가 만든 function 이름&quot; 이동&lt;/li&gt;
&lt;li&gt;화면 중간쯤 위치한 탭중 &amp;gt; TEST 탭 클릭&lt;/li&gt;
&lt;li&gt;Event Name을 지정해 주고, --payload에 해당하는 함수 입력값을 JSON 형태로 입력해 준다.&lt;/li&gt;
&lt;li&gt;그 다음 &quot;save&quot;버튼을 눌러 저장하고, &quot;Test&quot; 버튼을 눌러 테스트를 진행한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B30cz/btrHaXWrtyX/uIQsRfFiiOAPppj4WpLkG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B30cz/btrHaXWrtyX/uIQsRfFiiOAPppj4WpLkG1/img.png&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;665&quot; data-is-animation=&quot;false&quot; style=&quot;width: 40.3608%; margin-right: 10px;&quot; data-widthpercent=&quot;40.84&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B30cz/btrHaXWrtyX/uIQsRfFiiOAPppj4WpLkG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB30cz%2FbtrHaXWrtyX%2FuIQsRfFiiOAPppj4WpLkG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;725&quot; height=&quot;665&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kPmlv/btrHdIjBTlF/v1YWjNZBSrtKgRpwjrkUT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kPmlv/btrHdIjBTlF/v1YWjNZBSrtKgRpwjrkUT0/img.png&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;685&quot; data-is-animation=&quot;false&quot; style=&quot;width: 58.4764%;&quot; data-widthpercent=&quot;59.16&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kPmlv/btrHdIjBTlF/v1YWjNZBSrtKgRpwjrkUT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkPmlv%2FbtrHdIjBTlF%2Fv1YWjNZBSrtKgRpwjrkUT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1082&quot; height=&quot;685&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS Web Console&amp;gt;Lambda&amp;gt;Functions&amp;gt; &quot;my function&quot; 위치 (좌), Lambda Test 방법 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;563&quot; data-origin-height=&quot;163&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b90g21/btrHdbfCzdU/w5wGsamLZ3BGCPtJu6iDYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b90g21/btrHdbfCzdU/w5wGsamLZ3BGCPtJu6iDYk/img.png&quot; data-alt=&quot;실행 결과 (초록색).에러가 발생하는 빨강색. Details에는 결과 반환값들을 확인 할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b90g21/btrHdbfCzdU/w5wGsamLZ3BGCPtJu6iDYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb90g21%2FbtrHdbfCzdU%2Fw5wGsamLZ3BGCPtJu6iDYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;563&quot; height=&quot;163&quot; data-origin-width=&quot;563&quot; data-origin-height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 결과 (초록색).에러가 발생하는 빨강색. Details에는 결과 반환값들을 확인 할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;[ Lambda Function 생성 ]&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS CLI를 통한 Lambda 함수의 생성은 업데이트/수정과 비교하여 조금은 더 까다롭다. 그 이유는 권한/역할에 대한 설정 때문이다. 이 교육에서는 역할에 대한 설정은 사전 정의된 역할로 대체한다. 아래는 미리 정의된 역할중 &quot;lambdaPollyRole&quot;이라는 역할에 대한 리소스명(arn)을 구하고, &quot;roleArn&quot;에 저장한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657704756984&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;roleArn=$(aws iam list-roles --output text --query 'Roles[?contains(RoleName, `lambdaPollyRole`) == `true`].Arn')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lambda Function의 생성 자체는 이전 API 사용과 유사 하다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657704874391&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws lambda create-function \
--function-name create-function  \
--handler app.lambda_handler \
--runtime python3.9 \
--role $roleArn \
--environment Variables={TABLE_NAME=$notesTable} \
--zip-file fileb://create-function.zip&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;생성하고자 하는 function의 이름을 &quot;create-function&quot;, 소스의 압축파일 이름을 &quot;create-function.zip&quot;이라고 가정한다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;function update와 달리, configure를 한꺼번에 지정하여 생성하는 차이가 있다. handler, runtime, role, environment를 한꺼번에 지정하여 생성한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 이야기</category>
      <category>Amazon DynamoDB</category>
      <category>AWS CLI</category>
      <category>AWS Lambda 생성 관리</category>
      <category>AWS Lambda 함수 테스트</category>
      <category>AWS Lambda 호출</category>
      <category>DynamoDB python</category>
      <category>lambda function</category>
      <category>Lambda function python</category>
      <category>Lambda invoke</category>
      <category>Lambda를 활용한 application 개발</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/199</guid>
      <comments>https://windflex.tistory.com/199#entry199comment</comments>
      <pubDate>Wed, 13 Jul 2022 18:43:23 +0900</pubDate>
    </item>
    <item>
      <title>[AWS 교육 요약] - Developing on AWS (1/3)</title>
      <link>https://windflex.tistory.com/198</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nmPhS/btrG7YBggNz/fy5k36vDWnN8jA0FoKzae1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nmPhS/btrG7YBggNz/fy5k36vDWnN8jA0FoKzae1/img.png&quot; data-alt=&quot;AWS CLI를 활용한 자원 관리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nmPhS/btrG7YBggNz/fy5k36vDWnN8jA0FoKzae1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnmPhS%2FbtrG7YBggNz%2Ffy5k36vDWnN8jA0FoKzae1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;290&quot; height=&quot;174&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;174&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS CLI를 활용한 자원 관리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;[관련글]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/197&quot;&gt;2022.07.11 - [IT 이야기/IT 상식] - AWS교육[요약]-Technical Essential : IAM/Role/EC2/VPC/ELB&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/198&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.07.13 - [개발 이야기] - [AWS 교육 요약] - Developing on AWS (1/4)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/199&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.07.13 - [개발 이야기] - [AWS 교육 요약] Developing on AWS (2/4)&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ 교육 목표 ]&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발환경을 지원하도록 IAM 권한 구성&lt;/li&gt;
&lt;li&gt;AWS SDK를 사용한 Cloud Native Application 설계/구축/배포&lt;/li&gt;
&lt;li&gt;AWS 리소스 모니터링 및 유지 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[ 목표 서비스 아키텍처 - MSA ]&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfL4rF/btrG8zUxIrA/zfhppqZy5h5RnXC7e1vyPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfL4rF/btrG8zUxIrA/zfhppqZy5h5RnXC7e1vyPK/img.png&quot; data-alt=&quot;AWS 애플리케이션 서비스 아키텍처&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfL4rF/btrG8zUxIrA/zfhppqZy5h5RnXC7e1vyPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfL4rF%2FbtrG8zUxIrA%2FzfhppqZy5h5RnXC7e1vyPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1564&quot; height=&quot;822&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS 애플리케이션 서비스 아키텍처&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;AWS Web Console에서 AWS 서비스들을 제어 할 수 있지만, 서비스에 따라서는 프로그래밍 환경에서 제어가 될어야 할 필요성이 있다. AWS는 이러한 환경을 지원하기 위해, AWS CLI와 AWS SDK등과 같은 인터페이스를 제공하며, 이번 포스팅에서는 AWS CLI와 AWS SDK를 사용하여 환경구축/애플리케이션 개발하는 방법에 대하여 학습하는 과정을 요약 한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRI4Bt/btrG4eK19CX/32mK6WmD16LU8x8G021QaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRI4Bt/btrG4eK19CX/32mK6WmD16LU8x8G021QaK/img.png&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;644&quot; data-is-animation=&quot;false&quot; style=&quot;width: 52.3071%; margin-right: 10px;&quot; data-widthpercent=&quot;52.92&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRI4Bt/btrG4eK19CX/32mK6WmD16LU8x8G021QaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRI4Bt%2FbtrG4eK19CX%2F32mK6WmD16LU8x8G021QaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1586&quot; height=&quot;644&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uBWQH/btrG6dkflAf/1nM3UWc4dkj5oPVsiqP4sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uBWQH/btrG6dkflAf/1nM3UWc4dkj5oPVsiqP4sk/img.png&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;734&quot; data-is-animation=&quot;false&quot; style=&quot;width: 46.5301%;&quot; data-widthpercent=&quot;47.08&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uBWQH/btrG6dkflAf/1nM3UWc4dkj5oPVsiqP4sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuBWQH%2FbtrG6dkflAf%2F1nM3UWc4dkj5oPVsiqP4sk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1608&quot; height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS CLI와 SDK를 활용하여 AWS Service를 제어하는 예 (좌), AWS서비스를 제어하는 방법들 (우) AWS REST API를 활용하여 서비스 제어하며 REST API를 사용하는 인터페이스는 APP(1), AWS Console (2), AWS CLI (3), AWS SDK (4) 등을 지원하고 있다.&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;보안을 위해, 대부분은 AWS Request는 Access Key( Access Key ID와 Secret Access Key로 구성)로 서명해야 한다. AWS의 HTTP 전송하는 Request header에 인증정보를 추가해야 한다. AWS는 HTTP의 인증정보로 서명 버전 (SigV4)을 지원한다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;REST API를 기본 인터페이스로 한다는 것을 고려하면, 여러가지 동작이 이해하기 쉬워진다.&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS CLI는 다음 공식웹사이트를 참조 : &lt;a href=&quot;https://docs.aws.amazon.com/pt_br/cli/latest/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.aws.amazon.com/pt_br/cli/latest/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Python 용 AWS SDK (Boto3) 공식웹사이트 : &lt;a href=&quot;https://boto3.amazonaws.com/v1/documentation/api/latest/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://boto3.amazonaws.com/v1/documentation/api/latest/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Javascript/Node.js 용 AWS SDK: &lt;a href=&quot;https://aws.amazon.com/ko/sdk-for-javascript/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://aws.amazon.com/ko/sdk-for-javascript/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Java용 AWS SDK : &lt;a href=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/overview-summary.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/overview-summary.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;.Net용 AWS SDK : &lt;a href=&quot;https://docs.aws.amazon.com/sdkfornet/v3/apidocs/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.aws.amazon.com/sdkfornet/v3/apidocs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS Amplify Framework 공식 문서 : &lt;a href=&quot;https://docs.amplify.aws/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.amplify.aws/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS에서 개발하기 (SDK)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AWS Web Console을 사용하면 되지, 왜 SDK를 사용할까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 가지 이유가 있겠지만, 1) 프로그래밍으로 자동화 해야 하는 경우 (Web Browser 엔진을 돌려서 클릭할 수 없지는 않은가...), 2) Web Console의 위치를 일일이 찾는 것이 더 귀찮은 경우, 3) 여러가지 서비스와 방식이 복합적으로 연동되서 돌아가야 하는 경우, SDK가 더 쉬울 수도 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SDK 종류&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하위수준 API&lt;/li&gt;
&lt;li&gt;상위수준 API&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하위 수준의 API의 예 : &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;S3버킷의 리스트를 가져온다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1657614789827&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Retrieve the list of existing buckets
s3 = boto3.client('s3')
response = s3.list_buckets_v2(Bucket='mybucket')

for content in response['Contents']:
    print(f'  {content[&quot;Key&quot;]} : {content[&quot;LastModified&quot;]}')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상위 수준 API의 예: S3 버킷 리스트를 가져온다. (위와 동일 기능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상화를 통하여 좀 더 간결하게 사용할 수 있으며, 직접적인 구조 (JSON)으로 접근하지 않고, Method/Member처럼 접근해서 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657614871194&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Retrieve the list of existing buckets
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')

for obj in bucket.objects.all():
    print(f'  {obj.key} : {obj.last_modified')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;상위수준과 하위수준 API간 차이가....뭐 큰 차이는 없어 보인다. 따옴표 사용하는 횟수가 줄어들었다는 것 정도??&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS CLI (명령줄 인터페이스)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS CLI (명령줄)을 사용하면 Linux Shell, Windows CMD, MacOS Ternmina 등에서 바로 실행할 수 있으며, SSH/PuTTy, Cloud9 등에서 바로 제어가 가능한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;필자의 경우 CLI 명령어를 선호한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공식 문서 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/reference/&quot;&gt;https://docs.aws.amazon.com/cli/latest/reference/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS CLI 명령어의 기본 구조는 다음과 같다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657615656756&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ aws S3 ls s3://mybucket --recursive
$ aws s3 cp myfile.txt s3://mybucket
$ aws help
$ aws s3 ls help&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;명령어의 유형 : `AWS &amp;lt;서비스명&amp;gt; &amp;lt;명령어&amp;gt; &amp;lt;타겟&amp;gt; &amp;lt;후속 파라미터/매개변수&amp;gt; ...`. 매개변수가 필요하지 않은 `help`와 같은 명령어는 뒷쪽 입력이 필요없는 경우도 존재&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;AWS CLI는 기본적으로 `Botocore`라는 Python 라이브러리를 사용한다. 즉, Python SDK와 가장 유사한 동작을 한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; API의 동기/비동기&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* API 혹은 SDK 명령어는 대부분 비동기 방식 (Async.)로 동작한다. 만약, create db table 명령어를 요청 했다면, 반환된 값은 요청을 완료했다는 값이지, db table 생성이 완료되었다는 것을 의미하지는 않는다. 이 때문에, 비동기(async) 처리가 추가로 필요하다. AWS는 비동기 처리를 위해서는, 작업 완료까지 대기하는 waiter를 별도 지원한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 비동기 명령어의 예&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1657616478487&quot; class=&quot;gams&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ aws dynamodb describe-table --table-name Notes --query &quot;Table.TableStatus&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 결과가 반환될 때까지 대기 (Async 처리)&lt;/p&gt;
&lt;pre id=&quot;code_1657616478487&quot; class=&quot;gams&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws dynamodb wait table-exists --table-name Notes&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) SDK 버전에서의 비동기 처리 (Python)&lt;/h4&gt;
&lt;pre id=&quot;code_1657617002525&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dynamodb = boto3.resource('dynamodb')

table = dynamodb.create_table(
	TableName=table_name,
    KeySchema=[
    	{'AttributeName': 'year', 'KeyType': 'HASH'},  # Partition key
        {'AttributeName': 'title', 'KeyType': 'RANGE'}  # Sort key
    ],
    AttributeDefinitions=[
    	{'AttributeName': 'year', 'AttributeType': 'N'},
        {'AttributeName': 'title', 'AttributeType': 'S'}
	],
	ProvisionedThroughput={'ReadCapacityUnits': 10, 'WriteCapacityUnits': 10})
table.wait_until_exists()&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;`table.wait_until_exists()`를 통해서 완료될 때까지 대기 한다. 만약, 딱히 대기가 필요한 프로시저가 아니라면 굳이 대기할 필요는 없다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3) Waiter의 또다른 예&lt;/h4&gt;
&lt;pre id=&quot;code_1657617235492&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dynamodb = boto3.resource('dynamodb')

table = dynamodb.create_table( TableName=&quot;Notes&quot;, ..... )

table.meta.client.get_waiter('table_exists').wait(TableName=&quot;Notes&quot;)

print(table.item_count)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참조할만한 소스 코드 : &lt;a href=&quot;https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/python/example_code&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/python/example_code&lt;/a&gt;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;권한/인증&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한/인증 부분은 조금은 어려운 부분이다. 그렇지만 우선 이런것이 있다...하고 이해하고 넘어가 보자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실은, 조금 편하게 Cloud환경에서 개발하고 싶은데, 개발자가 인프라 담당자/보안담당자 처럼 이런 부분까지 Low Level로 설정해야 하나? 하는 생각이 들긴 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AWS 권한 / 정책&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서 컨텍스트에 대한 접근 허용/차단을 위한 권한부여는 정책을 사용한다. 정책은 크개 두가지 유형 1) 자격 증명 기반 정책과 2) 리소스 기반 정책이 있다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자격증명 기반 정책 : IAM 사용자 또는 그룹/역할에 연결된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;리소스 기반 정책 : 리소스에 연결 된다. 예) S3버킷에 정책을 연결한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서 권한 부여는 정책 (Policy)를 생성하고, 해당 권한에 Policy를 붙여서 권한을 부여하는 형태로 이루어 진다. 이 때 정책(Policy)는 JSON 형태로 표기한 문서를 의미한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IAM 사용자 혹은 사용자 그룹이 , AWS CLI, Shell, SDK, Console 등을 사용하여 접근 자원에 접근하려 한다. 이 때, 자격증명 기반 정책은 해당 사용자에게 권한을 부여 한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0brDM/btrG8IjLHEf/VGfEwRLFkiZVbnLSkdr81k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0brDM/btrG8IjLHEf/VGfEwRLFkiZVbnLSkdr81k/img.png&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;686&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.2553%; margin-right: 10px;&quot; data-widthpercent=&quot;47.81&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0brDM/btrG8IjLHEf/VGfEwRLFkiZVbnLSkdr81k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0brDM%2FbtrG8IjLHEf%2FVGfEwRLFkiZVbnLSkdr81k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1364&quot; height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FAjpd/btrG8XudtKp/tiJ6OcLPAW3VHOodwpHFWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FAjpd/btrG8XudtKp/tiJ6OcLPAW3VHOodwpHFWk/img.png&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;716&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.582%;&quot; data-widthpercent=&quot;52.19&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FAjpd/btrG8XudtKp/tiJ6OcLPAW3VHOodwpHFWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFAjpd%2FbtrG8XudtKp%2FtiJ6OcLPAW3VHOodwpHFWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1554&quot; height=&quot;716&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;s3:::notes에 대해 ListBucket을 허용하는 권한 정책을 사용자/사용자그룹에 부여 (좌), 특정IP 대역을 제외한 모든 사용자는 S3:::notes에 접근불가(Deny) 정책을 리소스(S3)에 부여 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역할(Role)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS 권한 분야에서 가장 중요하고 어렵기도 한 부분이다.&lt;/li&gt;
&lt;li&gt;역할의 중요 키워드는 &quot;임시성&quot;이다. 만료 기간이 정해진 임시 권한의 묶음이라고 할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;가령, 외주개발자에세 1달동안 접근 권한을 주고자 할 때, 권한을 부여했다가 1개월 후에 권한을 제거하는 방식으로 처리가 된다면 실수/오류 발생 가능성이 높아진다. 따라서, 이러한 경우 1달 만료하도록 설정된 권한을 부여한 역할(Role)을 생성하고 외주개발자에게 Role을 부여하면 된다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjHzLZ/btrG4GAKDrR/RSCso0IK90JEtUAKmx32Z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjHzLZ/btrG4GAKDrR/RSCso0IK90JEtUAKmx32Z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjHzLZ/btrG4GAKDrR/RSCso0IK90JEtUAKmx32Z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjHzLZ%2FbtrG4GAKDrR%2FRSCso0IK90JEtUAKmx32Z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;697&quot; height=&quot;311&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7amGx/btrG9lImPwh/KAOKu5yDG6Uiuzs8XZiyRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7amGx/btrG9lImPwh/KAOKu5yDG6Uiuzs8XZiyRk/img.png&quot; data-origin-width=&quot;558&quot; data-origin-height=&quot;562&quot; data-is-animation=&quot;false&quot; style=&quot;width: 45.4703%; margin-right: 10px;&quot; data-widthpercent=&quot;46.01&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7amGx/btrG9lImPwh/KAOKu5yDG6Uiuzs8XZiyRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7amGx%2FbtrG9lImPwh%2FKAOKu5yDG6Uiuzs8XZiyRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;558&quot; height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcJqvA/btrG8HFae9e/kwLzQhdkSooaeHxx2cbZVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcJqvA/btrG8HFae9e/kwLzQhdkSooaeHxx2cbZVK/img.png&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;738&quot; data-is-animation=&quot;false&quot; width=&quot;273&quot; height=&quot;234&quot; data-widthpercent=&quot;53.99&quot; style=&quot;width: 53.3669%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcJqvA/btrG8HFae9e/kwLzQhdkSooaeHxx2cbZVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcJqvA%2FbtrG8HFae9e%2FkwLzQhdkSooaeHxx2cbZVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;738&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;권한/정책에서 권한은 최소 권한 사용을 원칙으로 한다. (좌), 권한에 대한 중복/충돌이 발생할 수 있는데, 권한을 평가하는 우선순위는 &quot;거부/차단&quot;정책이 있는가를 우선 적용한다. 즉, 차단 정책과 허용 정책이 있다면 &quot;차단&quot;이 적용된다. 그리고 특별히 거론하지 않는 경우 거부 (Deny All)이 적용된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정책 평가 로직 참조 : &lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS Cloud 9 - AWS IDE&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dB1Vuf/btrG7YAC9x7/fJNXJbZaKA3WV3KtlsQUq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dB1Vuf/btrG7YAC9x7/fJNXJbZaKA3WV3KtlsQUq1/img.png&quot; style=&quot;width: 65.3254%; margin-right: 10px;&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;478&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;66.09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dB1Vuf/btrG7YAC9x7/fJNXJbZaKA3WV3KtlsQUq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdB1Vuf%2FbtrG7YAC9x7%2FfJNXJbZaKA3WV3KtlsQUq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1532&quot; height=&quot;478&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Yb7L8/btrG2uGPv6m/8QdsT3Y0j8Kkc0IRnsZKj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Yb7L8/btrG2uGPv6m/8QdsT3Y0j8Kkc0IRnsZKj1/img.png&quot; style=&quot;width: 33.51183595485978%;&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;1304&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;33.91&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Yb7L8/btrG2uGPv6m/8QdsT3Y0j8Kkc0IRnsZKj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYb7L8%2FbtrG2uGPv6m%2F8QdsT3Y0j8Kkc0IRnsZKj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2144&quot; height=&quot;1304&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS IDE-Cloud9의 특징 (좌) AWS IDE (Cloud9) 초기 모습 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AWS cloud 9&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;AWS에서 제공하는 Cloud 형 IDE이다. AWS EC2, S3, Lambda 등과 연계된 작업을 한다면 최적의 환경을 제공한다. 겉으로 보기에는 VS Code와 유사한 환경을 제공하며, AWS 관련 CLI / SDK 등 환경이 기본 세팅되어 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;AWS cloud9을 실행 후 좀 더 상세하게 보면, 해당 환경의 EC2 Instance를 살펴 보면 다음과 같이 Cloud9은 Cloud9용 Instance가 이미 구동되어 있다. EC2의 Security 탭에 가보면, IAM Role이 이미 부여되어 있는 것을 알 수 있다. 부여된 Role의 이름은 위에서 사용한 &quot;notes-appolication-role&quot;임을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BCMtg/btrG8HSdwNq/cYw1yhQLWDkmCsvzUCKtrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BCMtg/btrG8HSdwNq/cYw1yhQLWDkmCsvzUCKtrk/img.png&quot; data-alt=&quot;Cloud9을 위한 EC2 인스턴스가 생성되어 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BCMtg/btrG8HSdwNq/cYw1yhQLWDkmCsvzUCKtrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBCMtg%2FbtrG8HSdwNq%2FcYw1yhQLWDkmCsvzUCKtrk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;859&quot; height=&quot;142&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Cloud9을 위한 EC2 인스턴스가 생성되어 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;개발 환경 구축 (Practice -1)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Cloud9의 개발 환경중 하단의 터미널 창에서 &quot;aws configure&quot; 명령어를 통해 기본 개발환경에 대한 설정을 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1657673564258&quot; class=&quot;ebnf&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws configure&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위와 같이 aws cli 명령어를 통하여 기본 설정을 할 수 있다. AWS Access Key ID, Access Key, Region, Format등을 설정해 준다. 별도 Role이 설정 되어 있다면 어차피 개인 증명은 동작하지 않기 때문에, Acces Key ID, Access Key는 그냥 엔터를 치고 넘어가면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bD1kIy/btrG4GAa6Jj/4tEGXMwLwASki0jtzss6jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bD1kIy/btrG4GAa6Jj/4tEGXMwLwASki0jtzss6jk/img.png&quot; data-alt=&quot;aws configure 명령어를 통하여 설정하는 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bD1kIy/btrG4GAa6Jj/4tEGXMwLwASki0jtzss6jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbD1kIy%2FbtrG4GAa6Jj%2F4tEGXMwLwASki0jtzss6jk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;192&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;aws configure 명령어를 통하여 설정하는 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 Role을 확인 하는 방법 : `aws sts get-caller-identity`&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1096&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mKQS9/btrG4fW5U5d/rdXW2tjCeRlPz4PD7yLek0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mKQS9/btrG4fW5U5d/rdXW2tjCeRlPz4PD7yLek0/img.png&quot; data-alt=&quot;현재 부여된 Role을 확인 &amp;amp;lt;- `aws sts get-caller-identity`&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mKQS9/btrG4fW5U5d/rdXW2tjCeRlPz4PD7yLek0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmKQS9%2FbtrG4fW5U5d%2FrdXW2tjCeRlPz4PD7yLek0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1096&quot; height=&quot;186&quot; data-origin-width=&quot;1096&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;현재 부여된 Role을 확인 &amp;lt;- `aws sts get-caller-identity`&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;S3 버킷을 리스트 하는 명령어 : `aws s3 ls`&lt;/li&gt;
&lt;li&gt;S3 버킷을 삭제 `rb` 명령어 : `aws s3 rb s3:// &amp;lt;버킷이름&amp;gt; `&lt;/li&gt;
&lt;li&gt;IAM 권한 중 특정 Policy를 해당 Role &quot;notes-application-role&quot;에 부여&amp;nbsp; :&lt;br /&gt;`aws iam attach-role-policy --policy-arn &amp;lt;정책이름&amp;gt; --role-name notes-application-role`&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;권한 할당을 위해서는 정책이름은 자원명 (arn)으로 입력해야 한다. 그런데, S3 Delete Bucket 정책의 ARN은 어떻게 확보할 수 있을까?&amp;nbsp; &quot;S3-Delete-Bucket-Policy&quot; 정책의 ARN은 다음과 같은 명령어를 통하여 변수로 만들 수 있다.&amp;nbsp;&lt;br /&gt;`policyArn=$(aws iam list-policies --output text --query 'Policies[?PolicyName == `S3-Delete-Bucket-Policy`].Arn')`&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IAM Role : &quot;notes-application-role&quot;에 부여된 권한(permission)은 ReadOnlyAccess와 SSM(?)에 대한 권한만 존재함을 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m5nUi/btrG3La1plu/9j4oEe8DKmqfDTHo7JDjn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m5nUi/btrG3La1plu/9j4oEe8DKmqfDTHo7JDjn0/img.png&quot; style=&quot;width: 60.1727%; margin-right: 10px;&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;236&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;60.88&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m5nUi/btrG3La1plu/9j4oEe8DKmqfDTHo7JDjn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm5nUi%2FbtrG3La1plu%2F9j4oEe8DKmqfDTHo7JDjn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;719&quot; height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KaBBp/btrG3J5nyOk/vhpKKIDKTBJF7OPqVMHgyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KaBBp/btrG3J5nyOk/vhpKKIDKTBJF7OPqVMHgyk/img.png&quot; style=&quot;width: 38.664513715219655%;&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;236&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;39.12&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KaBBp/btrG3J5nyOk/vhpKKIDKTBJF7OPqVMHgyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKaBBp%2FbtrG3J5nyOk%2FvhpKKIDKTBJF7OPqVMHgyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;462&quot; height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;SDK 활용 S3버킷 생성/삭제/파일업로드 (Practice-2)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;795&quot; data-origin-height=&quot;524&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6pStD/btrG6V4LZAP/y4NgXAefNEdE9OXKOnxuw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6pStD/btrG6V4LZAP/y4NgXAefNEdE9OXKOnxuw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6pStD/btrG6V4LZAP/y4NgXAefNEdE9OXKOnxuw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6pStD%2FbtrG6V4LZAP%2Fy4NgXAefNEdE9OXKOnxuw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;795&quot; height=&quot;524&quot; data-origin-width=&quot;795&quot; data-origin-height=&quot;524&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CreateBucket (Boto3)&lt;/h3&gt;
&lt;pre id=&quot;code_1657608873694&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import boto3, botocore, configparser

def main(s3Client):
    print('\nStart of create bucket script\n')

    print('Reading configuration file for bucket name...')
    config = readConfig()
    bucket_name = config['bucket_name']

    print('Verifying that the bucket name is valid...')
    #### Verify that the bucket exists. The script with exit 
    #### if the name is not valid for a new bucket.
    verifyBucketName(s3Client, bucket_name)
    print(bucket_name)

    #### Create the notes-bucket-
    createBucket(s3Client, bucket_name)

    ##Pause until the the bucket is in the account
    print('\nConfirm that the bucket exists...')
    verifyBucket(s3Client, bucket_name)

    print('\nEnd of create bucket script\n')

def verifyBucketName(s3Client, bucket):
    try:
        ## Start TODO 2: enter a command that will check if a bucket already exists in AWS
        ## with the name built from your ini file input.
        
        # s3Client.list_buckets(Bucket=bucket)
        s3Client.head_bucket(Bucket=bucket)

        ## End TODO 2

        # If the previous command is successful, the bucket is already in your account.
        raise SystemExit('This bucket has already been created in your account, exiting because there is nothing further to do!')
    except botocore.exceptions.ClientError as e:
        error_code = int(e.response['Error']['Code'])
        if error_code == 404:
          ## If you receive a 404 error code, a bucket with that name
          ##  does not exist anywhere in AWS.
          print('Existing Bucket Not Found, please proceed')
        if error_code == 403:
          ## If you receive a 403 error code, a bucket exists with that
          ## in another AWS account.
          raise SystemExit('This bucket has already owned by another AWS Account, change the suffix and try a new name!')

def createBucket(s3Client, name):
    session = boto3.session.Session()

    # Obtain the region from the boto3 session
    current_region = session.region_name
    print('\nCreating ' + name + ' in ' + current_region)

    # Start TODO 3: Create a new bucket in the users current region 
    # and return the response in a response variable.
    if current_region == 'us-east-1':
        response = s3Client.create_bucket(Bucket=name)
    else:
        response = s3Client.create_bucket(
          Bucket=name,
          CreateBucketConfiguration={
              'LocationConstraint': current_region
          })
    
    
    # End TODO 3:

    print('Success!')

def verifyBucket(s3Client, bucket):
    ## Start TODO 4: Complete the function so that it will 
    ## pause and only proceed after the bucket exists.
    waiter = s3Client.get_waiter('bucket_exists')
    waiter.wait(Bucket=bucket)  

    ## End TODO 4
    print('The bucket:' + bucket + ' is now available.')

## Utility methods
def readConfig():
    config = configparser.ConfigParser()
    config.read('./labRepo/config.ini')
    
    return config['S3']

## TODO 1: Create an S3 client to interact with the service and pass 
## it to the main function that will create the buckets

client = boto3.client('s3')

## End TODO 1

try:
    main(client)
except botocore.exceptions.ClientError as err:
    print(err.response['Error']['Message'])
except botocore.exceptions.ParamValidationError as error:
    print(error)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657608154966&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;awsstudent:~/environment $ python labRepo/create-bucket.py 

Start of create bucket script

Reading configuration file for bucket name...
Verifying that the bucket name is valid...
Existing Bucket Not Found, please proceed
notes-bucket-sjlee-0010701

Creating notes-bucket-sjlee-0010701 in us-west-2
Success!

Confirm that the bucket exists...
The bucket:notes-bucket-sjlee-0010701 is now available.

End of create bucket script&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjmMwR/btrG4GNPvDT/qlPYcQ22QGY5bmaAW5yzt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjmMwR/btrG4GNPvDT/qlPYcQ22QGY5bmaAW5yzt0/img.png&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;133&quot; data-is-animation=&quot;false&quot; style=&quot;width: 92.3908%; margin-right: 10px;&quot; data-widthpercent=&quot;93.48&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjmMwR/btrG4GNPvDT/qlPYcQ22QGY5bmaAW5yzt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjmMwR%2FbtrG4GNPvDT%2FqlPYcQ22QGY5bmaAW5yzt0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;749&quot; height=&quot;133&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m78XI/btrG8WuQjFo/3m25X4O0be5LG5Z6afdnZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m78XI/btrG8WuQjFo/3m25X4O0be5LG5Z6afdnZ0/img.png&quot; data-origin-width=&quot;178&quot; data-origin-height=&quot;453&quot; data-is-animation=&quot;false&quot; style=&quot;width: 6.44644%;&quot; data-widthpercent=&quot;6.52&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m78XI/btrG8WuQjFo/3m25X4O0be5LG5Z6afdnZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm78XI%2FbtrG8WuQjFo%2F3m25X4O0be5LG5Z6afdnZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;178&quot; height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657608762326&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import boto3, botocore, configparser

def main(s3Client):
    print('\nStart of create object script\n')
    ## Initialize variables for object creation

    print('Reading configuration file for bucket name...')
    config = readConfig()
    bucket_name = config['bucket_name']
    source_file_name = config[&quot;object_name&quot;] + config['source_file_extension']
    key_name = config['key_name']+ config['source_file_extension']
    contentType = config['source_content_type']
    metaData_key = config['metaData_key']
    metaData_value = config['metaData_value']

    #### Create object in the s3 bucket
    print('Creating Object...')
    print(uploadObject(s3Client, bucket_name, source_file_name, key_name, contentType, {metaData_key: metaData_value}))
    
    print('\nEnd of create object script\n')

def uploadObject(s3Client, bucket, name, key, contentType, metadata={}):

    ## Start TODO 5: create a object by transferring the file to the S3 bucket, 
    ## set the contentType of the file and add any metadata passed to this function.
    
    response = s3Client.upload_file(
        Bucket=bucket, 
        Key=key,
        Filename=name,
        ExtraArgs={
            'ContentType': contentType,
            'Metadata': metadata
            }
    )
    
    
    ## End TODO 5
    return &quot;Finished creating object\n&quot;
    
def readConfig():
    config = configparser.ConfigParser()
    config.read('./labRepo/config.ini')
    
    return config['S3']

# Create an S3 client to interact with the service and pass 
# it to the main function that will create the buckets
client = boto3.client('s3')
try:
    main(client)
except botocore.exceptions.ClientError as err:
    print(err.response['Error']['Message'])
except botocore.exceptions.ParamValidationError as error:
    print(error)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pFeO3/btrG6WWWflV/5R9hIVtGkAKvohYYR2Vdx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pFeO3/btrG6WWWflV/5R9hIVtGkAKvohYYR2Vdx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pFeO3/btrG6WWWflV/5R9hIVtGkAKvohYYR2Vdx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpFeO3%2FbtrG6WWWflV%2F5R9hIVtGkAKvohYYR2Vdx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;703&quot; height=&quot;254&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 변환 후 업로드 (CSV -&amp;gt; JSON)&lt;/h3&gt;
&lt;pre id=&quot;code_1657609496106&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import boto3, botocore, json, csv, io, configparser

def main(s3Client):
    print('\nStart of convert object script\n')

    ## Initialize variables for object creation
    print('Reading configuration file for bucket name...')
    config = readConfig()
    bucket_name = config['bucket_name']
    source_file_name = config['object_name'] + config['source_file_extension']
    key_name = config['key_name']+ config['source_file_extension']
    processed_file_name = config['key_name'] + config['processed_file_extension']
    contentType = config['processed_content_type']
    metaData_key = config['metaData_key']
    metaData_value = config['metaData_value']

    #### Get the object from S3
    print('\nGetting the CSV object from S3 bucket')
    csvStr = getCSVFile(s3Client, bucket_name, key_name)
    
    ## Convert the object to the new format
    print('\nConverting CSV string to JSON...')
    jsonStr = convertToJSON(csvStr)
    
    ## Uploaded the converted object to S3
    print('Creating the new JSON object on S3')
    print(createObject(s3Client, bucket_name, processed_file_name, jsonStr, contentType, {metaData_key: metaData_value}))

    print('\nEnd of convert object script\n')

def getCSVFile(s3Client, bucket, key):
    bytes_buffer = io.BytesIO()
    
    ## Start TODO 6: Download the file contents to the 
    ## bytes_buffer object so that it can be decoded to a string.
    s3Client.download_fileobj(
        Bucket=bucket, 
        Key=key, 
        Fileobj=bytes_buffer)
    

    ## End TODO 6

    byte_value = bytes_buffer.getvalue()
    return byte_value.decode('utf-8')

def createObject(s3Client, bucket, key, data, contentType, metadata={}):
    ## Start TODO 7: Create an S3 object with the converted data
    s3Client.put_object(
        Bucket=bucket, 
        Key=key,
        Body=data,
        ContentType=contentType,
        Metadata=metadata
    )
    

    ## End TODO 7
    
    return 'Successfully Created Object\n'

def convertToJSON(input):
    jsonList = []
    keys = []
    
    csvReader = csv.reader(input.split('\n'), delimiter=&quot;,&quot;)

    for i, row in enumerate(csvReader):
        if i == 0:
            keys = row
        else:
            obj = {}
            for x, val in enumerate(keys):
                obj[val] = row[x]
            jsonList.append(obj)
    return json.dumps(jsonList, indent=4)

def readConfig():
    config = configparser.ConfigParser()
    config.read('./labRepo/config.ini')
    
    return config['S3']

# Create an S3 client to interact with the service and pass 
# it to the main function that will create the buckets
client = boto3.client('s3')
try:
    main(client)
except botocore.exceptions.ClientError as err:
    print(err.response['Error']['Message'])
except botocore.exceptions.ParamValidationError as error:
    print(error)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;파일 처리가 아니라, 메모리에서 처리하고 메모리로 부터 업로드 하는 것에 유의 한다. 따라서, 이전에 Bucket에 object 를 업로드 할 때와 달리, `s3Client.download_fileobject()`와 `s3Client.put_object()`를 사용한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;110&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxxnFA/btrG4IdPSBM/IOPRlgZunoCCvlUflwa9x0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxxnFA/btrG4IdPSBM/IOPRlgZunoCCvlUflwa9x0/img.png&quot; data-alt=&quot;notes.json 파일이 추가로 업로드 되어 있는 것을 확인 할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxxnFA/btrG4IdPSBM/IOPRlgZunoCCvlUflwa9x0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxxnFA%2FbtrG4IdPSBM%2FIOPRlgZunoCCvlUflwa9x0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;730&quot; height=&quot;110&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;110&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;notes.json 파일이 추가로 업로드 되어 있는 것을 확인 할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;b&gt;S3 정적 웹호스팅 설정 -&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷 이름이 표함된 버킷 이름을 변수명으로 저장&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고정된 버킷 이름 보다는 동적으로 찾는 형태로 변화수화 하기 (저수준의 api 인 &quot;s3api&quot; 사용)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1657609915655&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$&amp;gt; mybucket=$(aws s3api list-buckets --output text --query 'Buckets[?contains(Name, `notes-bucket`) == `true`].Name')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 동기화 (html/아래 파일과 s3 bucket의 파일을 동기화)&lt;/p&gt;
&lt;pre id=&quot;code_1657610349474&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws s3 sync ~/environment/labRepo/html/. s3://$mybucket/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ldaWm/btrG8mnx4c4/javDgca2iqGUHYutEPNZSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ldaWm/btrG8mnx4c4/javDgca2iqGUHYutEPNZSK/img.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;102&quot; data-is-animation=&quot;false&quot; style=&quot;width: 68.2139%; margin-right: 10px;&quot; data-widthpercent=&quot;69.02&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ldaWm/btrG8mnx4c4/javDgca2iqGUHYutEPNZSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FldaWm%2FbtrG8mnx4c4%2FjavDgca2iqGUHYutEPNZSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;614&quot; height=&quot;102&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bz2cxd/btrG8R1AgtP/2EDT6CpiFswAFJsmmwylK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bz2cxd/btrG8R1AgtP/2EDT6CpiFswAFJsmmwylK0/img.png&quot; data-origin-width=&quot;681&quot; data-origin-height=&quot;252&quot; data-is-animation=&quot;false&quot; style=&quot;width: 30.6233%;&quot; data-widthpercent=&quot;30.98&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bz2cxd/btrG8R1AgtP/2EDT6CpiFswAFJsmmwylK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbz2cxd%2FbtrG8R1AgtP%2F2EDT6CpiFswAFJsmmwylK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;681&quot; height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;파일 동기화 aws cli 명령어 실행 결과 (좌), 실형 결과를 AWS Console(web)에서 확인한 결과 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 호스팅 활성화&lt;/p&gt;
&lt;pre id=&quot;code_1657610143197&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$&amp;gt; aws s3api put-bucket-website --bucket $mybucket --website-configuration file://~/environment/labRepo/website.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한 정책 (policy) 부여&lt;/p&gt;
&lt;pre id=&quot;code_1657611211118&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws s3api put-bucket-policy --bucket $mybucket --policy file://~/environment/labRepo/policy.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정적 웹사이트 경로&lt;/p&gt;
&lt;pre id=&quot;code_1657611324977&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;printf &quot;\nYou can now access the website at:\nhttp://$mybucket.s3-website-$region.amazonaws.com\n\n&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;You can now access the website at: http://notes-bucket-xxxxx-xxxxxx.s3-website-us-west-2.amazonaws.com&lt;/blockquote&gt;</description>
      <category>개발 이야기</category>
      <category>AWS CLI</category>
      <category>aws python sdk</category>
      <category>aws s3 ls</category>
      <category>AWS S3 정적 웹사이트</category>
      <category>aws s3api</category>
      <category>AWS SDK</category>
      <category>AWS 개발환경 구축</category>
      <category>Boto3</category>
      <category>Cloud9</category>
      <category>python S3 bucket 생성</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/198</guid>
      <comments>https://windflex.tistory.com/198#entry198comment</comments>
      <pubDate>Wed, 13 Jul 2022 09:58:27 +0900</pubDate>
    </item>
    <item>
      <title>[AWS교육 요약]-Technical Essential : IAM/Role/EC2/VPC/ELB</title>
      <link>https://windflex.tistory.com/197</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oxrfP/btrGST1k00P/jVkNfduJE3DZSVUGEDGJnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oxrfP/btrGST1k00P/jVkNfduJE3DZSVUGEDGJnK/img.png&quot; data-alt=&quot;AWS 교육과정 요약 : AWS Technical Essentials. 참조 : AWS Training (https://aws.amazon.com)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oxrfP/btrGST1k00P/jVkNfduJE3DZSVUGEDGJnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoxrfP%2FbtrGST1k00P%2FjVkNfduJE3DZSVUGEDGJnK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;738&quot; height=&quot;369&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS 교육과정 요약 : AWS Technical Essentials. 참조 : AWS Training (https://aws.amazon.com)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[주요 내용 ]&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IAM 소개&lt;/li&gt;
&lt;li&gt;EC2 &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소개&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;AWS Lambda &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소개&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;VPC &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소개&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;AWS DB 서비스 소개&lt;/li&gt;
&lt;li&gt;AWS Networking &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소개&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;AWS Storage &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소개&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;AWS Farget&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소개&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Monitoring &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;소개&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;참조 :AWS Skill Builder 한글화 과정 목록&amp;nbsp; &lt;a href=&quot;https://github.com/serithemage/AWS_class_resources/tree/main/AWS_Skill_Builder&quot; data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;(&lt;/a&gt;&lt;a href=&quot;https://github.com/serithemage/AWS_class_resources/tree/main/AWS_Skill_Builder&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/serithemage/AWS_class_resources/tree/main/AWS_Skill_Builder)&lt;/a&gt;&lt;/blockquote&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Technical Essential - AWS 서비스에 대한 기초/교양과 같은 코스웍&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;AWS Technical Essential은 대학으로 치자면 교양과 같은 과목이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실제 각 관심있는 서비스와 프로비져닝, 활용에 대해 집중하기 보다는, 기초적인 서비스의 개념과 AWS가 추구하는 철학, 그리고 어떤 서비스들을 제공하는지 전체적인 큰그림을 그리는 과정이다.&amp;nbsp; 기초적인 설명과 관련된 실습 (Qwiklabs)를 해 볼수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;따라서, 만약 AWS에 대한 경험이 없다면 필수적으로 듣는것을 추천한다. 또한, AWS Certi.를 준비하신다면 당연하게도 필요한 영역이다.&amp;nbsp; 다만, 이미 AWS를 잘 알고 있고 사용중이며, 어떤한 목적으로 특정 서비스에 대한 사용방법을 익히고자 한다면 해당 과정은 적절하지 않을 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ AWS 기초 서비스에 대한 설명 ]&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리전/가용영역&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 1개 이상의 데이터 센터 묶음 가용영역, 2개 이상은 가용역역을 묶어서 리전&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 2개 이상의 가용영역으로 나누어서 DR&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 리전을 선택하는 것이다. 가용영역은 선택 안됨.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5YbSI/btrG0C4tA38/cFKv2BwO59U2zxugvu02GK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5YbSI/btrG0C4tA38/cFKv2BwO59U2zxugvu02GK/img.png&quot; data-alt=&quot;전세계 AWS 리전들.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5YbSI/btrG0C4tA38/cFKv2BwO59U2zxugvu02GK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5YbSI%2FbtrG0C4tA38%2FcFKv2BwO59U2zxugvu02GK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;491&quot; height=&quot;224&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전세계 AWS 리전들.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;엣지 로케이션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시 서비스. 미디어 콘텐츠가 로케이션 인근에 CDS와 같은 서비스 제공.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AWS 서비스 관리 방법 종류&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 1) AWS 관리 콘솔 (웹사이트), 2) AWS 명령줄 (AWS CLI), 3) AWS SDK (프로그래밍 언어별 지원되는 라이브러리)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;공동 책임 모델 다이어그램&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eEMta8/btrGS5AMXp5/k3iKvIevJupTkUFkvpauPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eEMta8/btrGS5AMXp5/k3iKvIevJupTkUFkvpauPK/img.png&quot; data-alt=&quot;AWS 보안 공동택임 모델.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eEMta8/btrGS5AMXp5/k3iKvIevJupTkUFkvpauPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeEMta8%2FbtrGS5AMXp5%2Fk3iKvIevJupTkUFkvpauPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;612&quot; height=&quot;266&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS 보안 공동택임 모델.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;인증/권한 - IAM (Identification Authority Management), Role (역할)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IAM root 유저 : Full Access 권한
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;권한을 줄일 수 없음. 작업용으로는 사용하지 말것. Billing 도구로만 사용. Multi-Factor 인증&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;일반 작업용 계정은 IAM User를 생성하여 사용할 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IAM User는 처음에 아무런 권한도 없음&lt;/li&gt;
&lt;li&gt;Policy를 통하여 권한을 부여함&lt;/li&gt;
&lt;li&gt;IAM User마다 권한을 부여하는 것은 매우 번거롭고 어려움 --&amp;gt; IAM User Group으로 그룹관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0tm8s/btrG1sUOpxj/MgRRZO9hvqlVf6K8Sa65N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0tm8s/btrG1sUOpxj/MgRRZO9hvqlVf6K8Sa65N1/img.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;588&quot; data-is-animation=&quot;false&quot; style=&quot;width: 29.024%; margin-right: 10px;&quot; data-widthpercent=&quot;29.72&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0tm8s/btrG1sUOpxj/MgRRZO9hvqlVf6K8Sa65N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0tm8s%2FbtrG1sUOpxj%2FMgRRZO9hvqlVf6K8Sa65N1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bU6Ghd/btrGQc02nNZ/0DH2XIZMiESW3gCO9cHT8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bU6Ghd/btrGQc02nNZ/0DH2XIZMiESW3gCO9cHT8k/img.png&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;400&quot; data-is-animation=&quot;false&quot; width=&quot;334&quot; height=&quot;205&quot; style=&quot;width: 39.6264%; margin-right: 10px;&quot; data-widthpercent=&quot;40.57&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bU6Ghd/btrGQc02nNZ/0DH2XIZMiESW3gCO9cHT8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbU6Ghd%2FbtrGQc02nNZ%2F0DH2XIZMiESW3gCO9cHT8k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;652&quot; height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HiBTj/btrGWzVftTj/hxLjaK3JOwQBkZKQRivr5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HiBTj/btrGWzVftTj/hxLjaK3JOwQBkZKQRivr5k/img.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;588&quot; data-is-animation=&quot;false&quot; style=&quot;width: 29.024%;&quot; data-widthpercent=&quot;29.71&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HiBTj/btrGWzVftTj/hxLjaK3JOwQBkZKQRivr5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHiBTj%2FbtrGWzVftTj%2FhxLjaK3JOwQBkZKQRivr5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;IAM 그룹 및 IAM 사용자 (좌). IAM Policy 의 예 (중), IAM 역할(Role) (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;Role (역할) ---&amp;gt; 중요&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적으로 Role은 임시적인 권한을 가정함&lt;/li&gt;
&lt;li&gt;외주 개발자가 참여할 경우 권한을 부여할 때, 기간 설정 (권한 만료)를 포함하여 권한을 설정함. (Assume)&lt;/li&gt;
&lt;li&gt;&amp;nbsp;임시로, Role을 부여 (STS Key)&lt;/li&gt;
&lt;li&gt;Role은 사용자 뿐만 아니라 서비스가 부여 받을 수도 있다. ex) 서비스용 EC2 (연동)이 Role을 부여 받을 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS 컴퓨팅 - EC2/ECS/EKS&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;EC2 인스턴스 (Elastic Compute Cloud)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VM이라고 하지 않고 &quot;인스턴스&quot;라고 명명. 즉, 언제든지 삭제/재기동/프로비져닝하는 용도라고 볼 수 있음&lt;/li&gt;
&lt;li&gt;크기 조정, 빠른 프로비저닝 (몇분 안에 시작), 사용한 만큼 요금 지불 (삭제하면 요금 증가하지 않음)&lt;/li&gt;
&lt;li&gt;인스턴스 유형 (어떤 OS, 크기), VPC/Subnet 등을 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ECS (Elatic Container Service)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bypKt9/btrGTwyeiuV/XDDiRavjr9c47SnRVby5XK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bypKt9/btrGTwyeiuV/XDDiRavjr9c47SnRVby5XK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bypKt9/btrGTwyeiuV/XDDiRavjr9c47SnRVby5XK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbypKt9%2FbtrGTwyeiuV%2FXDDiRavjr9c47SnRVby5XK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1298&quot; height=&quot;614&quot; data-origin-width=&quot;1298&quot; data-origin-height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECS --&amp;gt; MSA(마이크로서비스 아키텍처)로 컨테이너가 수백/수천개 이상이 되면, 이들을 관리해 주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Container Orchestration 서비스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;EKS (Elastic Kubenetes Service)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Container Orchestration 서비스 중 Kubenetes 형으로 특화 한 서비스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서버리스 (Serverless)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서버 관리를 하지 않아도 됨 : 서버 관리 (장애관리, 이중화, 백업, 규모조정, ... )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Lambda : 서버를 프로비저닝 하지 않고도 코드를 실행. 사용한 컴퓨팅 시간 만큼 요금. 코드가 실행되지 않으면 요금 청구되지 않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Lambda를 사용 --&amp;gt; 사실상 모든 유형의 App./Backend Code를 별다른 관리 없이 실행할수 있음.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sraj5/btrG0BLmFym/VkUDTqaMkZJNC8eBy4fxpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sraj5/btrG0BLmFym/VkUDTqaMkZJNC8eBy4fxpK/img.png&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;614&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sraj5/btrG0BLmFym/VkUDTqaMkZJNC8eBy4fxpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsraj5%2FbtrG0BLmFym%2FVkUDTqaMkZJNC8eBy4fxpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1338&quot; height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EMl7k/btrGV92xYo3/KZmG8xzL2KfKfBXQPiRkT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EMl7k/btrGV92xYo3/KZmG8xzL2KfKfBXQPiRkT0/img.png&quot; data-origin-width=&quot;1338&quot; data-origin-height=&quot;614&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EMl7k/btrGV92xYo3/KZmG8xzL2KfKfBXQPiRkT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEMl7k%2FbtrGV92xYo3%2FKZmG8xzL2KfKfBXQPiRkT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1338&quot; height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS 서버리스 서비스 종류 (좌), AWS Lambda flow (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;AWS Lambda에 대한 상세 내용 : &lt;a href=&quot;https://aws.amazon.com/ko/lambda/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://aws.amazon.com/ko/lambda/&lt;/a&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS Lambda를 이용한 파일처리&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zkYbV/btrGWyvmZjP/PBYmkTspokDa9O29T3wDmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zkYbV/btrGWyvmZjP/PBYmkTspokDa9O29T3wDmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zkYbV/btrGWyvmZjP/PBYmkTspokDa9O29T3wDmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzkYbV%2FbtrGWyvmZjP%2FPBYmkTspokDa9O29T3wDmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1848&quot; height=&quot;398&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS Lambda를 이용한 웹애플리케이션 구조&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2138&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NZm60/btrG2tF4a2w/tXZx82JtpOHlSdWf7iy1x0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NZm60/btrG2tF4a2w/tXZx82JtpOHlSdWf7iy1x0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NZm60/btrG2tF4a2w/tXZx82JtpOHlSdWf7iy1x0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNZm60%2FbtrG2tF4a2w%2FtXZx82JtpOHlSdWf7iy1x0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2138&quot; height=&quot;374&quot; data-origin-width=&quot;2138&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실습 - 1&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IAM User 및 권한 설정해 보기&lt;/li&gt;
&lt;li&gt;이미 User에 3개의 IAM 사용자가 생성되어 있음. User Groups에 이미 S3 권한, EC2 권한, Admin 권한으로 권한그룹이 설정되어 있음.&lt;/li&gt;
&lt;li&gt;실습의 목적은 User-1 : S3만 ReadOnly, User-2: EC2 ReadOnly, User-3 : Admin/Read/Start/Stop 권한으로 각각 독립적으로 설정하는 것이 목표임&lt;/li&gt;
&lt;li&gt;S3 ReadOnly, EC2 ReadOnly, Admin 의 각 권한에 가서 &quot;사용자 추가&quot;하여 권한을 등록하는 것이 실습 과정임&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bV9QkU/btrGYAzD6DK/JgXi5nC9Ehf2mG848dFxL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bV9QkU/btrGYAzD6DK/JgXi5nC9Ehf2mG848dFxL0/img.png&quot; data-origin-width=&quot;1222&quot; data-origin-height=&quot;954&quot; data-is-animation=&quot;false&quot; width=&quot;456&quot; height=&quot;356&quot; style=&quot;width: 42.0122%; margin-right: 10px;&quot; data-widthpercent=&quot;42.51&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bV9QkU/btrGYAzD6DK/JgXi5nC9Ehf2mG848dFxL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbV9QkU%2FbtrGYAzD6DK%2FJgXi5nC9Ehf2mG848dFxL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1222&quot; height=&quot;954&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bs3DC8/btrG20jHIDp/CMhFbxzOH14T8VbkKuvGp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bs3DC8/btrG20jHIDp/CMhFbxzOH14T8VbkKuvGp1/img.png&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;258&quot; data-is-animation=&quot;false&quot; style=&quot;width: 56.8251%;&quot; data-widthpercent=&quot;57.49&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bs3DC8/btrG20jHIDp/CMhFbxzOH14T8VbkKuvGp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbs3DC8%2FbtrG20jHIDp%2FCMhFbxzOH14T8VbkKuvGp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;447&quot; height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS Network - VPC&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kWrnn/btrG20ROWVr/Lk49AUu1o1mKbYghRB9Ij1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kWrnn/btrG20ROWVr/Lk49AUu1o1mKbYghRB9Ij1/img.png&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;648&quot; data-is-animation=&quot;false&quot; width=&quot;455&quot; height=&quot;254&quot; style=&quot;width: 40.9422%; margin-right: 10px;&quot; data-widthpercent=&quot;41.42&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kWrnn/btrG20ROWVr/Lk49AUu1o1mKbYghRB9Ij1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkWrnn%2FbtrG20ROWVr%2FLk49AUu1o1mKbYghRB9Ij1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1162&quot; height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSLUjh/btrG2tGEN4U/ha9vdS6AhUsVMVropgz6Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSLUjh/btrG2tGEN4U/ha9vdS6AhUsVMVropgz6Kk/img.png&quot; data-origin-width=&quot;1420&quot; data-origin-height=&quot;560&quot; data-is-animation=&quot;false&quot; style=&quot;width: 57.895%;&quot; data-widthpercent=&quot;58.58&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSLUjh/btrG2tGEN4U/ha9vdS6AhUsVMVropgz6Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSLUjh%2FbtrG2tGEN4U%2Fha9vdS6AhUsVMVropgz6Kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1420&quot; height=&quot;560&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VPC를 생성할 때,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1) 리전을 결정해야 함. 2) VPC 이름, 3) VPC IP 대역 설정 (Private)&lt;/li&gt;
&lt;li&gt;VPC는 기본적으로 외부와의 통신이 단절되어 있음.&amp;nbsp;Public Internet과 연결하려면, 인터넷 게이트웨이 (Internet GW)와 VPC를 연결이 되어야 한다. 여기에서 연결을 한다 함은 Routing Table에 등록해 주는 것을 의미한다.&amp;nbsp;&lt;br /&gt;Internet GW는 NAT (Network Address Translation)을 사용하여 Outbound로 인터넷은 연결하고, Inbound로는 연결되지 않도록 설정할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;기존 온프레미스 데이터센터와 전용선을 연결하듯이 연동은 어떻게 하는가? 가상 프라이빗 게이트웨이(VGW)를 만들고 VPC에 연결, 가상 프라이빗 게이트웨이와 데이터센터의 게이트웨이를 VPN으로 연결.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(방화벽 기능-유사 기능) 네트워크 차단/허용에 관한 부분은, AWS에서 다음과 같이 허용/차단 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IGW에 라우팅에 의한 차단/허용&lt;/li&gt;
&lt;li&gt;IAM 정책을 사용하여 액세스 제어&lt;/li&gt;
&lt;li&gt;NACL에 의한 IP/포트의 허용/차단 (상태 비저장 : Stateless)&lt;/li&gt;
&lt;li&gt;보안 그룹 (Security Group) 허용/차단 (상태 저장: Stateful)&lt;/li&gt;
&lt;li&gt;(Host에서) Iptables, Windows 방화벽 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;606&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vYrcb/btrG24GKcMV/dzpDHDKowKsKvuJF8K2dk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vYrcb/btrG24GKcMV/dzpDHDKowKsKvuJF8K2dk0/img.png&quot; data-alt=&quot;AWS 방화벽 및 네트워크 차단 기능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vYrcb/btrG24GKcMV/dzpDHDKowKsKvuJF8K2dk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvYrcb%2FbtrG24GKcMV%2FdzpDHDKowKsKvuJF8K2dk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;363&quot; height=&quot;346&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;606&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AWS 방화벽 및 네트워크 차단 기능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS 스토리지 - EBS / S3&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNBgiw/btrGQ6fqw5E/WHw0d2ATLYOfue7GvzlYO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNBgiw/btrGQ6fqw5E/WHw0d2ATLYOfue7GvzlYO1/img.png&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;658&quot; data-is-animation=&quot;false&quot; width=&quot;532&quot; height=&quot;247&quot; style=&quot;width: 46.9969%; margin-right: 10px;&quot; data-widthpercent=&quot;47.55&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNBgiw/btrGQ6fqw5E/WHw0d2ATLYOfue7GvzlYO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNBgiw%2FbtrGQ6fqw5E%2FWHw0d2ATLYOfue7GvzlYO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1418&quot; height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kzVXg/btrG2tUmmLI/RFnQkvC1TNKTL4zvQQd4Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kzVXg/btrG2tUmmLI/RFnQkvC1TNKTL4zvQQd4Uk/img.png&quot; data-origin-width=&quot;1412&quot; data-origin-height=&quot;594&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.8403%;&quot; data-widthpercent=&quot;52.45&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kzVXg/btrG2tUmmLI/RFnQkvC1TNKTL4zvQQd4Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkzVXg%2FbtrG2tUmmLI%2FRFnQkvC1TNKTL4zvQQd4Uk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1412&quot; height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS Storage : 인스턴스 스토어, EBS&amp;nbsp; (좌),&amp;nbsp; &amp;nbsp;S3 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EBS (Elastic Block Store)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2 인스턴스에 사용되는 소토리지는 임시 블록 수준 스토리지이다. 따라서, EC2 인스턴스를 중지하거나 종료하면 스토리지 데이터가 손실됨 (일시적이다.) 인스턴스가 중지/종료 될 때 데이터를 보존하려면, EBS를 사용하면 된다. EBS는 백업/스냅샷 등의 서비스를 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Amazon S3&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IAM 정책, 버킷 정책, ACL, 암호화 기능을 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3는 IAM 정책을 사용할 수 있다. 예를 들어 인스턴스에서 실행중인 앱플리케이션이 S3버킷에서 파일을 검색해야 하는 경우, IAM역할을 인스턴스에 연결하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3 버킷에 액세스 권한을 부여하는 또다른 방법은 버킷 정책을 사용하는 것이다. 버킷 정책은 JSON 기반 IAM 정책을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[S3의 기본 스토리지 클래스]&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Amazon S3 Standard : 기본 스토리지 클래스. 웹사이트/콘텐츠 배포와 같은 범용 스토리지. 데이터 가용영역이 최소 3개에 저장된다. (가용역역 3개가 동시에 삭제될 경우 극히 낮음)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;S3 Clacier&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; : 몇분 안에 검색할 수 있는 데이터를 보관. 1~5분 내에 데이터를 검색할 수 있다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;S3 Glacier Deep Archive&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; : 거의 액세스하지 않는 데이터를 보관. 변경후 데이터 검색하는 기본 시간은 12시간이다. 백업하는 용도로 적당한다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;AWS 데이터베이스&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yIJ2K/btrG2s9ftmr/Dj7pjPlX3KNh2sl54sRMyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yIJ2K/btrG2s9ftmr/Dj7pjPlX3KNh2sl54sRMyk/img.png&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;552&quot; data-is-animation=&quot;false&quot; width=&quot;547&quot; height=&quot;226&quot; style=&quot;width: 54.7088%; margin-right: 10px;&quot; data-widthpercent=&quot;55.35&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yIJ2K/btrG2s9ftmr/Dj7pjPlX3KNh2sl54sRMyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyIJ2K%2FbtrG2s9ftmr%2FDj7pjPlX3KNh2sl54sRMyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1336&quot; height=&quot;552&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YsFBO/btrGXgoGGlo/1AVYerwNwTlzXziJWkh9UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YsFBO/btrGXgoGGlo/1AVYerwNwTlzXziJWkh9UK/img.png&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;586&quot; data-is-animation=&quot;false&quot; style=&quot;width: 44.1284%;&quot; data-widthpercent=&quot;44.65&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YsFBO/btrGXgoGGlo/1AVYerwNwTlzXziJWkh9UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYsFBO%2FbtrGXgoGGlo%2F1AVYerwNwTlzXziJWkh9UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1144&quot; height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;AWS 지원 데이터베이스 유형 (좌), 데이터베이스 유형별 AWS서비스 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS에서 지원하는 8가지 유형의 데이터베이스 (일반, 관리형, 완전관리형)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관계형 데이터베이스 :&lt;span style=&quot;background-color: #f89009;&quot;&gt; RDS (관리형)&lt;/span&gt; , Aurora, Redshift&lt;/li&gt;
&lt;li&gt;Key-Value 데이터베이스 : DynamoDB&lt;/li&gt;
&lt;li&gt;인메모리 데이터베이스 : Memcached, Redis&lt;/li&gt;
&lt;li&gt;Document 데이터베이스&lt;/li&gt;
&lt;li&gt;와이드 컬럼 : Keyspaces&lt;/li&gt;
&lt;li&gt;Graph : neptune&lt;/li&gt;
&lt;li&gt;시계열 : Timestream&lt;/li&gt;
&lt;li&gt;원장 : OLDB&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[ Amazon RDS 서비스 ]&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H5feU/btrG3DIUJRq/RnQEz24xdhsoNyAp2KPoZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H5feU/btrG3DIUJRq/RnQEz24xdhsoNyAp2KPoZk/img.png&quot; data-alt=&quot;Amazon RDS 서비스 기본 구조도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H5feU/btrG3DIUJRq/RnQEz24xdhsoNyAp2KPoZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH5feU%2FbtrG3DIUJRq%2FRnQEz24xdhsoNyAp2KPoZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;394&quot; height=&quot;290&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Amazon RDS 서비스 기본 구조도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관계형 데이터베이스에 대한 관리형 서비스 (PaaS 형태로, 인프라 프로비저닝, 데이터베이스 설정/패치/백업 등 알아서 관리됨) 스 생성/&lt;/li&gt;
&lt;li&gt;내부적으로는 EC2 인스턴스 위에 RDS가 올라가서 구동되는 구조임 (기본적으로 Private Subnet)&lt;/li&gt;
&lt;li&gt;따라서, IAM 등 EC2에서 설정하는 부분은 대부분 설정이 가능함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[Amazon DynamoDB]&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;완전 관리형 Key-Value 데이터 베이스 (NoSQL)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;매우 우수한 확장성, 암호화 제공&lt;/li&gt;
&lt;li&gt;JSON 형태로 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;Amazon 모니터링(Monitoring)/로드밸런싱 서비스&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Amazon CloudWatch&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS 및 온프라미스 인프라 및 리소스를 실시간 모니터링&lt;/li&gt;
&lt;li&gt;단일 위치로 지표를 모두 보낼 수 있다. --&amp;gt; 단일 위치에서 여러 리소스를 모두 모니터링/관리 가능&lt;/li&gt;
&lt;li&gt;경보 대응 및 자동화 : CPU/Memory 등 리소스 사용 알람, 네트워크/트래픽, 로그,&amp;nbsp; 비용 알람 등&lt;/li&gt;
&lt;li&gt;CloudWatch 경보를 생서하여, 대시보드 등을 쉽게 관리 할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUNIZN/btrGYzhcKxD/NZ1OwMVAJGmlN8whAF5C40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUNIZN/btrGYzhcKxD/NZ1OwMVAJGmlN8whAF5C40/img.png&quot; data-origin-width=&quot;1456&quot; data-origin-height=&quot;664&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.6408%; margin-right: 10px;&quot; data-widthpercent=&quot;50.22&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUNIZN/btrGYzhcKxD/NZ1OwMVAJGmlN8whAF5C40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUNIZN%2FbtrGYzhcKxD%2FNZ1OwMVAJGmlN8whAF5C40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1456&quot; height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQYfV3/btrGXga7ZOP/0kkpVKjY088A0DGUZ2aV70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQYfV3/btrGXga7ZOP/0kkpVKjY088A0DGUZ2aV70/img.png&quot; data-origin-width=&quot;1230&quot; data-origin-height=&quot;566&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.1965%;&quot; data-widthpercent=&quot;49.78&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQYfV3/btrGXga7ZOP/0kkpVKjY088A0DGUZ2aV70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQYfV3%2FbtrGXga7ZOP%2F0kkpVKjY088A0DGUZ2aV70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1230&quot; height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Amazon CloutWatch. 네임스페이스(자원 태그), EC2 지표 38개 지표 중 관심 지표만 선택 (차원) , 대시보드의 예 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[로드 밸런싱]&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ELB (Elastic Load Balancing) : 웹 애플리케이션의 트래픽에 따라서 로드밸런싱 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S84Rs/btrG3D3far8/owT5FOMFwpWtxjOPaYRf91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S84Rs/btrG3D3far8/owT5FOMFwpWtxjOPaYRf91/img.png&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;620&quot; data-is-animation=&quot;false&quot; width=&quot;662&quot; height=&quot;301&quot; style=&quot;width: 35.4013%; margin-right: 10px;&quot; data-widthpercent=&quot;35.82&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S84Rs/btrG3D3far8/owT5FOMFwpWtxjOPaYRf91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS84Rs%2FbtrG3D3far8%2FowT5FOMFwpWtxjOPaYRf91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1364&quot; height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SJIzr/btrG20SbqFN/x82KzGSnYEpAKTXTdrWKv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SJIzr/btrG20SbqFN/x82KzGSnYEpAKTXTdrWKv1/img.png&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;346&quot; data-is-animation=&quot;false&quot; style=&quot;width: 63.4359%;&quot; data-widthpercent=&quot;64.18&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SJIzr/btrG20SbqFN/x82KzGSnYEpAKTXTdrWKv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSJIzr%2FbtrG20SbqFN%2Fx82KzGSnYEpAKTXTdrWKv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1364&quot; height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Amazon ELB 기본 구조 (좌), Amazon Load Balancer의 유형(우). Application Load Balancer (L7), Network Load Balancer (L4), Classic Load Balancer (L4/L7이지만 과거 유지 버전). 자세한 내용은 https://aws.amazon.com/elasticloadbalancing 참조.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Application Load Balancer &amp;amp; Network Load Balancer&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M603Z/btrG3rPxlZd/euk49Bdr8EAYdCvRVkVzu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M603Z/btrG3rPxlZd/euk49Bdr8EAYdCvRVkVzu1/img.png&quot; data-origin-width=&quot;1344&quot; data-origin-height=&quot;468&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.1065%; margin-right: 10px;&quot; data-widthpercent=&quot;49.68&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M603Z/btrG3rPxlZd/euk49Bdr8EAYdCvRVkVzu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM603Z%2FbtrG3rPxlZd%2Feuk49Bdr8EAYdCvRVkVzu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1344&quot; height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0bT6o/btrGYyvPTyf/EonJuu1DXKeJ8miqkgTPq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0bT6o/btrGYyvPTyf/EonJuu1DXKeJ8miqkgTPq0/img.png&quot; data-origin-width=&quot;1332&quot; data-origin-height=&quot;458&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.7307%;&quot; data-widthpercent=&quot;50.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0bT6o/btrGYyvPTyf/EonJuu1DXKeJ8miqkgTPq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0bT6o%2FbtrGYyvPTyf%2FEonJuu1DXKeJ8miqkgTPq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1332&quot; height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Application Load Balancer (L7) 부하 분산으로 지원하는 기능 (좌), Network Load Balancer 부하분산 지원 기능 (우)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byO0AB/btrG3kJKADd/7NwApCcMfcKwmDl4c776Ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byO0AB/btrG3kJKADd/7NwApCcMfcKwmDl4c776Ek/img.png&quot; data-alt=&quot;로드 밸런서의 종류별 차이에 대한 도식화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byO0AB/btrG3kJKADd/7NwApCcMfcKwmDl4c776Ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyO0AB%2FbtrG3kJKADd%2F7NwApCcMfcKwmDl4c776Ek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;973&quot; height=&quot;396&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로드 밸런서의 종류별 차이에 대한 도식화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ Auto Scaling ]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Amazon EC2 Auto Scaling의 구성요소
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시작 템플릿 : EC2를 시작할 때 정책 --&amp;gt; 당연하게도 &lt;u&gt;&lt;b&gt;동적으로 신규 인스턴스를 구동&lt;/b&gt;&lt;/u&gt;해야 하므로, 그 때 어떤 인스턴스를 구동할지 이미지를 정해 주어야 한다. EC2를 신규 생성하는 과정과 유사하다.&lt;/li&gt;
&lt;li&gt;조정 정책 : 어떤 상황이 되면 몇개까지 &lt;u&gt;&lt;b&gt;인스턴스를 증가할 것인지 정책&lt;/b&gt;&lt;/u&gt;을 지정&lt;/li&gt;
&lt;li&gt;Amazon EC2 Auto Scaling 그룹 : Auto Scaling이 적용할 &lt;u&gt;&lt;b&gt;대상 그룹&lt;/b&gt;&lt;/u&gt;을 지정해 주어야 한다.&amp;nbsp; &lt;br /&gt;--&amp;gt; LB를 선택하고, 앞서 설정한, 대상을 지정하고 (VPC지정), 시작템플릿을 지정하고, 조정 정책을 정해주고, 알람 등을 설정해 주는 최종 단계&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vsy6M/btrGY2Qxja4/A3yCAFkRnIiWvGqXfvu53k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vsy6M/btrGY2Qxja4/A3yCAFkRnIiWvGqXfvu53k/img.png&quot; data-origin-width=&quot;1448&quot; data-origin-height=&quot;612&quot; data-is-animation=&quot;false&quot; width=&quot;713&quot; height=&quot;301&quot; style=&quot;width: 56.2475%; margin-right: 10px;&quot; data-widthpercent=&quot;56.91&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vsy6M/btrGY2Qxja4/A3yCAFkRnIiWvGqXfvu53k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVsy6M%2FbtrGY2Qxja4%2FA3yCAFkRnIiWvGqXfvu53k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1448&quot; height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pluas/btrG241mLAO/mOKQo8g4ZmJKiSfRVidW0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pluas/btrG241mLAO/mOKQo8g4ZmJKiSfRVidW0K/img.png&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;518&quot; data-is-animation=&quot;false&quot; style=&quot;width: 42.5897%;&quot; data-widthpercent=&quot;43.09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pluas/btrG241mLAO/mOKQo8g4ZmJKiSfRVidW0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpluas%2FbtrG241mLAO%2FmOKQo8g4ZmJKiSfRVidW0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;928&quot; height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;크기 조정 (Auto Scaling) : 수직 크기 조정, 수평크기 조정. Amazon Auto Scaling은 수평 크기 조정을 의미함. Auto Scaling 그룹의 예 (우) : 처음에는 3개 인스턴스로&amp;nbsp; 시작, 트래픽이 작으면 2개로 줄이고, 트래픽이 많으면 5개로 증대.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;로드밸런스 (Application LB) 실습&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;895&quot; data-origin-height=&quot;85&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba1IIV/btrG4f2mWzf/XFag6oVYkHyyZx6pIXKxO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba1IIV/btrG4f2mWzf/XFag6oVYkHyyZx6pIXKxO1/img.png&quot; data-alt=&quot;초기 상태. Web Applicaiton용 EC2 인스턴스가 1개 구동되어 있음.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba1IIV/btrG4f2mWzf/XFag6oVYkHyyZx6pIXKxO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba1IIV%2FbtrG4f2mWzf%2FXFag6oVYkHyyZx6pIXKxO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;895&quot; height=&quot;85&quot; data-origin-width=&quot;895&quot; data-origin-height=&quot;85&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;초기 상태. Web Applicaiton용 EC2 인스턴스가 1개 구동되어 있음.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKEoZ4/btrG24mZfwU/dpnTuxHh62BWXqHSgPt9w0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKEoZ4/btrG24mZfwU/dpnTuxHh62BWXqHSgPt9w0/img.png&quot; data-alt=&quot;구동중인 Web Application에는 Admin Tool로써 Stress Testing 기능이 포함되어 있음. 기능 동작 시 10분동안 CPU 부하를 줌&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKEoZ4/btrG24mZfwU/dpnTuxHh62BWXqHSgPt9w0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKEoZ4%2FbtrG24mZfwU%2FdpnTuxHh62BWXqHSgPt9w0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1262&quot; height=&quot;120&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구동중인 Web Application에는 Admin Tool로써 Stress Testing 기능이 포함되어 있음. 기능 동작 시 10분동안 CPU 부하를 줌&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;191&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7v5wB/btrG4ckcvlY/ZrVsmLuKiod46ZlSQKJYMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7v5wB/btrG4ckcvlY/ZrVsmLuKiod46ZlSQKJYMK/img.png&quot; data-alt=&quot;CPU 부하를 몇분 가하고 난 다음 다시 EC2 인스턴스를 살펴보면, 인스턴스가 3개로 늘어나 있음을 확인 할 수 있다. Name Field에 &amp;quot;-&amp;quot;로 표현된것이 증가된 인스턴스 이다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7v5wB/btrG4ckcvlY/ZrVsmLuKiod46ZlSQKJYMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7v5wB%2FbtrG4ckcvlY%2FZrVsmLuKiod46ZlSQKJYMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;733&quot; height=&quot;191&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;191&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CPU 부하를 몇분 가하고 난 다음 다시 EC2 인스턴스를 살펴보면, 인스턴스가 3개로 늘어나 있음을 확인 할 수 있다. Name Field에 &quot;-&quot;로 표현된것이 증가된 인스턴스 이다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>AWS Technical Essentials</category>
      <category>AWS 기본 교육</category>
      <category>AWS 에센셜</category>
      <category>cloudWatch</category>
      <category>EC2</category>
      <category>IAM</category>
      <category>lambda</category>
      <category>S3</category>
      <category>로드밸런서</category>
      <category>역할 role</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/197</guid>
      <comments>https://windflex.tistory.com/197#entry197comment</comments>
      <pubDate>Mon, 11 Jul 2022 18:25:17 +0900</pubDate>
    </item>
    <item>
      <title>[텐서플로우] TFIO/TFIO.audio 설치 에러 - NotImplementedError</title>
      <link>https://windflex.tistory.com/196</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텐서플로우(Tesorflow)를 이용한 오디오 파이프라인을 구성하려고 할 때,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tensorflow-io에서 다음과 같은 에러가 발생하는 일이 빈번하다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657094050794&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NotImplementedError: unable to open file: libtensorflow_io.so #1313&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tensorflow에서는 GPU 관련하여 버전이 안맞으면 이러한 에러가 자주 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(tensorflow-io와 기존 tensorflow/cuda/cuDNN의 버전이 안맞는 경우)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 필자의 경우는, TFIO를 사용해서 오디오를 로드해야만 하는 상황이었다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657094340734&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tfio.audio.AudioIOTensor(...)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링을 해도 여러가지 해법이 동작하지 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중 몇개의 댓글에서 해답을 찾았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[해결 방안]&lt;/p&gt;
&lt;pre id=&quot;code_1657094203262&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;!pip install tensorflow_io==0.23.1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`tensorflow_io==0.23.1`을 설치 해라..&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;그런데, 어떤때는 `tensorflow-io`이고, 어떤 경우는 `tensorflow_io`로 dash(-)와 underscore(_) 차이가 있는듯 하다...&amp;nbsp;&lt;br /&gt;이름은 `tensorflow-io`이고 설치 패키지명은 `tensorflow_io` 이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 id=&quot;conversation-title&quot;&gt;&amp;nbsp;&lt;/h1&gt;</description>
      <category>개발 이야기</category>
      <category>AudioIOTensor</category>
      <category>NotImplementedError</category>
      <category>tensorflow-io 설치에러</category>
      <category>tensorflow_io</category>
      <category>tfio</category>
      <category>tfio audio</category>
      <category>tfio 버전</category>
      <category>텐서플로우 io</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/196</guid>
      <comments>https://windflex.tistory.com/196#entry196comment</comments>
      <pubDate>Wed, 6 Jul 2022 17:02:03 +0900</pubDate>
    </item>
    <item>
      <title>[맥북-NTFS] 맥북에서 윈도우 외장하드(NTFS) 쓰기(mount) - 모든버전 사용 가능</title>
      <link>https://windflex.tistory.com/195</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvbaPW/btrF3ZAMnEI/mgaeLtYogY4OQ8KeRPCvb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvbaPW/btrF3ZAMnEI/mgaeLtYogY4OQ8KeRPCvb0/img.png&quot; data-alt=&quot;맥북에서 NTFS를 사용해 보자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvbaPW/btrF3ZAMnEI/mgaeLtYogY4OQ8KeRPCvb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvbaPW%2FbtrF3ZAMnEI%2FmgaeLtYogY4OQ8KeRPCvb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;357&quot; height=&quot;357&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;맥북에서 NTFS를 사용해 보자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;맥북 (MacOS)는 파일시스템 (FileSystem)이 윈도우의 그것과 다르기 때문에, 윈도우용으로 사용하던 외장하드/외장SSD/USB등의 쓰기를 사용할 수 없다. 다행하게도 읽기는 지원을 해주지만, 아래 처럼 쓰기가 되지 않는다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&quot;정보 가져오기&quot;를 통해서 디스크 정보를 보면, &quot;읽기만 가능&quot;으로 표기 되어 있다. 실제 디스크의 폴더에 접근하여 &quot;새폴더 만들기&quot; 등이 팝업메뉴에 출력되지 않으며, 당연하게도 &quot;파일복사&quot; 등이 되지 않는다.&amp;nbsp;맥북의 내장 SSD 용량 부족으로 데이터를 백업하거나, 윈도우용으로 사용하던 USB담아서 파일을 옮기려고 할 때, 매우 곤란을 겪게 된다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;패러랠즈, VMware 또는 부트캠프(Bootcamp) 등을 사용하여 윈도우와 같이 OS를 사용하는 유저의 경우에는 불편하더라도 파일복사/백업 방법이 있지만, 이 또한 패러럴즈/VMware를 추가 구동해야 하고, 복사를 다수회 진행해야 할 수도 있다. 또한, 부트캠프는 리부팅 후 윈도우즈 부팅을 해야 하기 때문에 상황에 따라서는 아예 선택지에서 제외 해야 하는 경우도 존재한다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;FAT32 등 OS와 무관하게 공용으로 사용하는 파일시스템은 모두 사용 가능하다. 그러나, FAT32 파일 시스템은 4G이상의 파일을 저장하지 못한다. (2^32 -&amp;gt; 4*GB)&amp;nbsp;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crYrYM/btrF5ep0O24/bTpEWMsmCjA3hraY094eGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crYrYM/btrF5ep0O24/bTpEWMsmCjA3hraY094eGK/img.png&quot; data-origin-width=&quot;251&quot; data-origin-height=&quot;288&quot; data-is-animation=&quot;false&quot; style=&quot;width: 46.4137%; margin-right: 10px;&quot; data-widthpercent=&quot;46.96&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crYrYM/btrF5ep0O24/bTpEWMsmCjA3hraY094eGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrYrYM%2FbtrF5ep0O24%2FbTpEWMsmCjA3hraY094eGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;251&quot; height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/COyi8/btrF5Ji7KNO/khiwielnKlWaWakQYsEkyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/COyi8/btrF5Ji7KNO/khiwielnKlWaWakQYsEkyK/img.png&quot; data-origin-width=&quot;189&quot; data-origin-height=&quot;192&quot; data-is-animation=&quot;false&quot; style=&quot;width: 52.4235%;&quot; data-widthpercent=&quot;53.04&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/COyi8/btrF5Ji7KNO/khiwielnKlWaWakQYsEkyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCOyi8%2FbtrF5Ji7KNO%2FkhiwielnKlWaWakQYsEkyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;189&quot; height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;맥북 (MacOS)에서 윈도우즈용 디스크의 정보가져오기 (좌). 디스크에 대한 권한이 읽기만 가능으로 되어 있다. 윈도우용 디스크에서 팝업메뉴 (우). 새폴더 만들기 등의 메뉴 자체가 없으며, 파일복사/이동 등 쓰기 관련한 기능이 아예 동작하지 않는다.&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이러한 이유로 우리는 맥북(최근 Monterey 포함)에서 &quot;윈도우용 디스크 (NTFS)&quot;에 대한 쓰기 권한으로 열기가 필요하다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;구글을 검색해 보면, 유사한 사례로 &lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&quot;맥북에서 NTFS 쓰기 방법&quot;&lt;/span&gt;&lt;/b&gt; 등에 대한 다양한 정보가 나올것이다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mounty application 설치&lt;/li&gt;
&lt;li&gt;NTFS 지원용 유료 Application 설치&lt;/li&gt;
&lt;li&gt;/etc/fstab mount 방법&lt;/li&gt;
&lt;li&gt;수동 mount 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;결론부터 말하면, 유료 Application 설치 방법 외 나머지 방법들은 모두 해 보았으나, 필자의 환경 (Monterey 12.2.1)에서는 다수의 방법이 동작하지 않았다. 필자의 경우는 수동 mount 방법만이 동작하여 그 방법과, 그외 방법들을 소개한다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;직접 수동 Mount 해서 사용한다&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;수동 마운트 (Mount) 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;수동 마운트라고 해서 걱정할 것 없다. &lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;NTFS 디스크를 마운트하기 위해서는, 다음과 같은 정보를 확인하고 수행 하면 된다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마운트하고자 하는 디스크(NTFS용 디스크)의 디바이스명&lt;/li&gt;
&lt;li&gt;마운트하고자 하는 위치 (폴더, 신규 생성)&lt;/li&gt;
&lt;li&gt;마운트 명령어 수행 ( NTFS 디바이스 이름 --&amp;gt; 마운트폴더 )&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;한번 수작업 하고 나면, 쉘스크립트 등으로 자동화해 사용해도 좋을 것이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;실제 수행할 명령어만을 먼저 리스트업 해보면 다음과 같다.&amp;nbsp; (이게 이 포스팅의 핵심이다.)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1656505591771&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ diskutil list
$ sudo mkdir /Volumes/disk2s2
$ sudo mount -t ntfs -o rw,auto,nobrowse /dev/disk2s2 /Volumes/disk2s2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이제 위 명령어를 하나씩 살펴 보도록하자.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;우리의 목적을 다시 말하면, NTFS 디스크에 쓰기 권한을 부여하고 마운트(mount)하는 것이다. 즉, 다음과 같은 형태가 최종 목적이라는 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;$ mount&amp;nbsp; &amp;nbsp;&amp;lt;NTFS파일시스템&amp;gt;&amp;nbsp; &amp;lt;읽기/쓰기권한&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;디스크이름&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;마운트할 폴더&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;여기에서 부족한 정보를 확보하고 mount를 실행해 주면 되는것이라 하겠다. 위에서 우리가 모르는 것이 무엇일까? 나머지는 형식에 맞게 표기해 주면 되지만, 정확한 &quot;&amp;lt;디스크이름&amp;gt;&quot;을 알지 못한다. linux에서는 `sda0` `sdb0` 등의 이름을 사용하는데, MacOS에서는 다른 네이밍 체계를 가지고 있다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;구글을 검색하면, /etc/fstab/을 이용하 마운트를 자동화 해주는 방법들이 검색 된다. 그런데 여기에서 문제점이 정확한 &quot;디바이스명&quot;을 가이드 하지 않는다. 디바이스이름이 아니라, `SSD` `WindowsDisk`등의 디스플레이 네임을 표기하면 된다는 설명이 있는데, 이렇게 하면 동작하지 않는다. MacOS에서 자체적으로 어떤 추가/편의 프로세스가 있을지 모르겠지만, Linux Mount를 조금 아는 사람이라면 이렇게 동작하지 않을 것을 알것이다. 저 디스크 이름은 단순히 표기상의 구분일 뿐이다. 정확한 DeviceID가 필요하다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위와 같은 이유로, 정확히 OS에서 인지하는 Device ID를 구해야 한다. 이를 위해서 &lt;u&gt;`diskutil list`&lt;/u&gt;를 실행해 본다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;실행 1) diskutil list&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;954&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2IZUB/btrF4vsoMJ7/PHN6uuJR6mVjgOfQUuiy1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2IZUB/btrF4vsoMJ7/PHN6uuJR6mVjgOfQUuiy1K/img.png&quot; data-alt=&quot;diskutil list 명령어를 통하여, 실제 OS가 인식하고 있는 Disk 볼륨을 확인할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2IZUB/btrF4vsoMJ7/PHN6uuJR6mVjgOfQUuiy1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2IZUB%2FbtrF4vsoMJ7%2FPHN6uuJR6mVjgOfQUuiy1K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1364&quot; height=&quot;954&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;954&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;diskutil list 명령어를 통하여, 실제 OS가 인식하고 있는 Disk 볼륨을 확인할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;`diskutil list`를 실행하면 위와 같은 결과를 볼 수 있다. 윈도우즈에서 `disk part`등과 비슷한 화면이다.&amp;nbsp; 여러 항목이 나오지만 대부분 내장 디스크에 대한 정보이고, 하단으로 중간쯤 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;`/dev/disk2 (external, physical)`&lt;/span&gt;에서 외장물리디스크에 관한 섹션인것을 확인 할 수 있다. 이 중에서 &quot;GUID_partition_scheme&quot; 디스크볼륨은 아니고 볼륨구조에 대한 스키마 이므로 직접적인 마운트 대상은 아니다. 따라서, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;3번째에 있는 &quot;Microsoft Basic Data SSD&quot;가 대상이며 디바이스ID &quot;disk2s2&quot; 인것을 확인 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;`/dev/disk3`는 가상디스크/이미지의 영역이다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;실행 2) 마운트할 대상 폴더 생성 : mkdir /Volumes/disk2s2&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마운트할 대상 위치에 폴더를 하나 생성한다. 마운트후에 이 폴더가 디스크 역할을 대신 할 것이다. 일반 디스크와 동일하게 취급하기 위해서 `/Volumes/`하단에 폴더를 생성하도록 하자. 또는 본인의 취향에 따라서 편한 위치에 생성해도 된다. 또, 마운트할 폴더명 (추후 디스크명)을 지정하여 `mkdir`을 실행해 주면 된다. 필자의 경우는 Disk ID 이름과 동일하게 `disk2s2`라고 지정하였다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$ sudo mkdir /Volumes/disk2s2&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;`/Volumes`은 관리자영역이므로 하위 폴더 생성에 `sudo`가 필요하다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;실행 3) Mount : mount -t NTFS -o rw,auto,nobrowse &amp;lt;디스크id&amp;gt; &amp;lt;마운트 대상 폴더&amp;gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위에서 정보 (디스크 ID: disk2s2)와 마운트할 폴더 (/Volumes/disk2s2)를 확보하였다. 이제 실제 마운트만 해 주면 우리는 맥북(MacOS)에서 NTFS 디스크를 사용하여 읽고/쓰기를 할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음과 같이 실행해 주면 된다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;$&amp;nbsp;sudo&amp;nbsp;mount&amp;nbsp;-t&amp;nbsp;ntfs&amp;nbsp;-o&amp;nbsp;rw,auto,nobrowse&amp;nbsp;/dev/disk2s2&amp;nbsp;/Volumes/disk2s2&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위 명령을 수행하고 나면, 다음과 같이 동일이름을 가진 디스크 드라이브가 추가 생성되어 있는 것을 확인할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zaVFm/btrF6KhG65c/rJEU8Huhf7ikYVMdKYQYr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zaVFm/btrF6KhG65c/rJEU8Huhf7ikYVMdKYQYr0/img.png&quot; data-origin-width=&quot;389&quot; data-origin-height=&quot;236&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;65.78&quot; style=&quot;width: 65.011%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zaVFm/btrF6KhG65c/rJEU8Huhf7ikYVMdKYQYr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzaVFm%2FbtrF6KhG65c%2FrJEU8Huhf7ikYVMdKYQYr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;389&quot; height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drmqhd/btrF2N12iIy/owK2vNE08vhsfHGxcSKcG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drmqhd/btrF2N12iIy/owK2vNE08vhsfHGxcSKcG0/img.png&quot; data-origin-width=&quot;247&quot; data-origin-height=&quot;288&quot; data-is-animation=&quot;false&quot; style=&quot;width: 33.8262%;&quot; data-widthpercent=&quot;34.22&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drmqhd/btrF2N12iIy/owK2vNE08vhsfHGxcSKcG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdrmqhd%2FbtrF2N12iIy%2FowK2vNE08vhsfHGxcSKcG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;247&quot; height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;추가적인 디스크 SSD가 /Volume/에 생성되어 있다. (좌). 사실 이 디스크는 /Volume/disk2s2 이다. 해당 디스크는 원래의 디스크와 달리 팝업메뉴에 &quot;이름변경&quot;등 기존 &quot;읽기&quot;권한 으로 수행할 수 없는 메뉴가 포함되어 있다. 디스크 정보를 보면 권한항목에 &quot;사용자 설정으로 연결함&quot;이라고 표시 되어 있다.&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이 신규 디스크 &quot;SSD&quot;는 실제 이름은 &quot;disk2s2&quot;이지만, 디스크 드라이브 이름 (디스플레이 이름)으로 변경 출력되는 것이다.&amp;nbsp; 위에서 잠깐 언급했지만, 구글링으로 검색되는 &quot;/etc/fstab&quot; 등록 방법은 이러한 디스크의 이름을 지정해 줄 때 명시성이 부족해서 잘 동작하지 않는다. 또한, &quot;disk2s2&quot;라는 Device ID는 디스크가 구동될 때마다 숫자가 달라질 수 있다. 따라서 &quot;/etc/fstab&quot;에 등록해 두고 자동화 할 수 있을지는 의문이다. (외장하드 포트를 절대 빼지 않는 다는 가정이 있으면 가능할 지도 모르겠다.)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b177CL/btrF4dFFl4B/F7xLmqQsULr2td1LML6NZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b177CL/btrF4dFFl4B/F7xLmqQsULr2td1LML6NZ1/img.png&quot; data-alt=&quot;SSD 디스크 중 쓰기가 가능한 디스크의 원래 이름은 disk2s2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b177CL/btrF4dFFl4B/F7xLmqQsULr2td1LML6NZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb177CL%2FbtrF4dFFl4B%2FF7xLmqQsULr2td1LML6NZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1208&quot; height=&quot;264&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SSD 디스크 중 쓰기가 가능한 디스크의 원래 이름은 disk2s2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;마운트 된 결과를 확인해 보자:&amp;nbsp; `mount`를 실행해 보면 마운트가 결려있는 정보를 나열해 준다. 결과를 확인해 보면 `/dev/disk2s2`가 마운트 되어 있음을 확인할 수 있다. 또한, 이전에 소개한적 있던 안드로이드 (Android)에 파일을 전송하는 애플리케이션 또한 유사한 방법으로 마운트가 걸려 있는 것을 알수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://richwind.co.kr/104&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;참조 : 2020.05.10 - [IT 이야기/IT 상식] - [맥북] 맥북-안드로이드 USB 연결 (ft. MacOS - Android File Transfer)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1424&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwbkmz/btrF4vMLYpH/QKcJdagkhVVohxIIuCy56k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwbkmz/btrF4vMLYpH/QKcJdagkhVVohxIIuCy56k/img.png&quot; data-alt=&quot;마운트가 설정되어 있는 결과를 확인할 수 있다. 안드로이드 파일 전송 프로그램도 비슷한 방식을 사용하고 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwbkmz/btrF4vMLYpH/QKcJdagkhVVohxIIuCy56k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbwbkmz%2FbtrF4vMLYpH%2FQKcJdagkhVVohxIIuCy56k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1424&quot; height=&quot;420&quot; data-origin-width=&quot;1424&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마운트가 설정되어 있는 결과를 확인할 수 있다. 안드로이드 파일 전송 프로그램도 비슷한 방식을 사용하고 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이제 우리는 NTFS 외장하드(SSD)에 자유롭게 파일 쓰기를 할수 있다. 맥북의 부족한 하드디스크의 고통을 완화할 수 있는 수단이다. 데이터파일 등은 외장SSD로 빠르게 사용할 수 있을 것이다.&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;(참고로 필자는 윈도우즈 머신에서 내장 SSD로 사용하던 것을 외장으로 쓰는 방법을 사용하고 있다. 매우 빠르게 내장과 유사한 속도로 사용할 수 있어서 편리하다. 대용량을 지원하기 때문에, USB메모리와는 차원이 다른 편의성이 있다. 또한 필요에 따라서는 다시 윈도우즈 머신에서 사용한다.)&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;181&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zkfAQ/btrF2N12DKM/EUrcpGYRSkkCA22dfO7E00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zkfAQ/btrF2N12DKM/EUrcpGYRSkkCA22dfO7E00/img.png&quot; data-alt=&quot;이제 NTFS 디스크/외장하드에 새로운 파일 쓰기를 자유롭게 할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zkfAQ/btrF2N12DKM/EUrcpGYRSkkCA22dfO7E00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzkfAQ%2FbtrF2N12DKM%2FEUrcpGYRSkkCA22dfO7E00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;298&quot; height=&quot;181&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;181&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이제 NTFS 디스크/외장하드에 새로운 파일 쓰기를 자유롭게 할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;4) 마운트 삭제 (다른 마운트를 삭제하지 않도록 주의할것)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마운트한 결과가 필요 없으면 마운트 설정을 제거하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 마운트 포지션이 제거되지 않도록 2번~3번 확인하고 삭제하도록 하자...&lt;/p&gt;
&lt;pre id=&quot;code_1656510562307&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo umount -f /Volumes/disk2s2&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ mount -f &amp;lt;마운트한 폴더&amp;gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;or&amp;nbsp; &amp;nbsp; mount -f &amp;lt;마운트한 디스크ID&amp;gt;&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;ERROR : Read-only file system&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종종 아래와 같이, &quot;Read-only file system&quot;이라는 에러가 발생할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1658715789699&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mount_ntfs: /dev/disk2s2 on /Users/windstream/ExtDrive: Read-only file system
mount: /Users/windstream/ExtDrive failed with 71&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;아래부터는 구글에서 검색되는 mounty 애플리케이션과 /etc/fstab을 사용하는 방법을 간략히 정리하였다. 필요에 따라 사용할 수 있을 것이니 참조하기 바란다.&lt;/h4&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;b&gt;mounty 설치 방법&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1656500656771&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install --cask mounty&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zxbwf/btrF5Hep9mf/CCD44lOCxa5BPqc1kSNQN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zxbwf/btrF5Hep9mf/CCD44lOCxa5BPqc1kSNQN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zxbwf/btrF5Hep9mf/CCD44lOCxa5BPqc1kSNQN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZxbwf%2FbtrF5Hep9mf%2FCCD44lOCxa5BPqc1kSNQN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1258&quot; height=&quot;236&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpwHi5/btrF0ldh4qw/7rjkP6vxlM7vwy5tfkQyWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpwHi5/btrF0ldh4qw/7rjkP6vxlM7vwy5tfkQyWK/img.png&quot; data-origin-width=&quot;389&quot; data-origin-height=&quot;83&quot; data-is-animation=&quot;false&quot; style=&quot;width: 79.9766%; margin-right: 10px;&quot; data-widthpercent=&quot;80.92&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpwHi5/btrF0ldh4qw/7rjkP6vxlM7vwy5tfkQyWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpwHi5%2FbtrF0ldh4qw%2F7rjkP6vxlM7vwy5tfkQyWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;389&quot; height=&quot;83&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blB9rS/btrF2N8z8Co/u8IvK81aEddNBQS9lPMEZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blB9rS/btrF2N8z8Co/u8IvK81aEddNBQS9lPMEZ0/img.png&quot; data-origin-width=&quot;147&quot; data-origin-height=&quot;133&quot; data-is-animation=&quot;false&quot; style=&quot;width: 18.8607%;&quot; data-widthpercent=&quot;19.08&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blB9rS/btrF2N8z8Co/u8IvK81aEddNBQS9lPMEZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblB9rS%2FbtrF2N8z8Co%2Fu8IvK81aEddNBQS9lPMEZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;147&quot; height=&quot;133&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;/etc/fstab에 mount 설정 방법&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1656505573444&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo nano /etc/fstab&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기/IT 상식</category>
      <category>MacOS NTFS write</category>
      <category>mounty</category>
      <category>NTFS 마운트</category>
      <category>맥북 NTFS</category>
      <category>맥북 NTFS Mount</category>
      <category>맥북 NTFS 쓰기 연결</category>
      <category>맥북 윈도우 외장하드</category>
      <category>맥북 윈도우즈 디스크 쓰기</category>
      <category>맥북 윈도우즈 하드디스크 연결</category>
      <category>맥북에서 윈도우 디스크 사용</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/195</guid>
      <comments>https://windflex.tistory.com/195#entry195comment</comments>
      <pubDate>Wed, 29 Jun 2022 23:14:20 +0900</pubDate>
    </item>
    <item>
      <title>[Python] 파이썬 모듈/패키지 파해치기 - 모듈 생성하기/불러오기/상대경로/절대경로</title>
      <link>https://windflex.tistory.com/194</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yZ6EQ/btrFHKDNJoK/gWKpNTHXc4K8RPjJdRsYO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yZ6EQ/btrFHKDNJoK/gWKpNTHXc4K8RPjJdRsYO0/img.png&quot; data-alt=&quot;파이썬 모듈과 패키지에 대해여 자세히 알아보자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yZ6EQ/btrFHKDNJoK/gWKpNTHXc4K8RPjJdRsYO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyZ6EQ%2FbtrFHKDNJoK%2FgWKpNTHXc4K8RPjJdRsYO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;404&quot; height=&quot;296&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;파이썬 모듈과 패키지에 대해여 자세히 알아보자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;모듈 : 함수들이 뭉쳐진 하나의 .py 파일&amp;nbsp;&lt;br /&gt;패키지 : 여러 개의 모듈을 그룹화한 묶음&lt;br /&gt;라이브러리 : 패키지의 모음을 그룹화&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[목차]&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파이썬 모듈 만들기&lt;/li&gt;
&lt;li&gt;파이썬 모듈 불러오기 (상대경로, 절대경로, 환경변수 등록)&lt;/li&gt;
&lt;li&gt;파이썬 모듈 실행 : __name__의 의미&lt;/li&gt;
&lt;li&gt;패키지와의 관계&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;파이썬 모듈 (Python Module)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;모든 python 파일 (*.py)는 모듈이며, 각 모듈은 `import`를 통해서 모듈을 추가 할 수 있다. 또한 모듈 안의 모든 함수와 개체 또한 모듈로 볼 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1656163333009&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import 모듈이름&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예를 들어, 다음과 같은 코드를 `calc.py`로 저장한 경우를 가정하자.&lt;/h4&gt;
&lt;pre id=&quot;code_1656163441625&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# calc.py
def add(a,b):
	return a+b&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;모듈 불러오기&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이 경우 다음과 같이 모듈을 추가할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1656163520395&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import calc
print( calc.add(10, 20) )&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;`import calc.py`와 같이 확장자는 포함하지 않음에 주의한다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;또한 다음과 같이 `from`을 사용할 수 있다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1656163650289&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from calc import add
print( add(10, 20) )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;다른위치의 모듈 불러오기&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;지금까지는 동일한 디렉토리에 존재하는 모듈을 불러왔으나, 모듈파일이 다른위치에 있으면 어떻게 불러올 수 있을까?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 상대경로 사용 (Relative Path)&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;상대경로는 별다른 설정 없이 다른 위치에 있는 모듈을 바로 추가 할 수 있는 방법이다. 그러나, 그 모듈의 위치가 하위 디렉토리 혹은 부모/형제 디렉토리에 위치하는 모듈 정도에 적용하는 것이 적당하다. 제 3의 독립적인 위치에 적용하는 것은 어려울뿐만 아니라 에러 발생가능성이 높아 진다.&amp;nbsp;&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하위 디렉토리이 있는 모듈을 추가하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1656164328092&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;form child.dir.path import module_name&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상위 디렉토리/형제 디렉토리에 있는 모듈 파일을 추가하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1656164433088&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from ..parent.sibling.path import module_name&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2) sys.path 추가 하기 (sys.path.append)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1656164164077&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; sys.path.append(모듈을 저장한 디렉터리)&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사실상, 하위디렉터리가 아닌 경우 가장 많이 사용되는 module 추가 방법이다. `sys.path.append( path_dir )`을 사용하여 python 이 구동되는 기본 path를 추가하는 방법이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음과 같이 `sys.path`에 python의 기본 구동 디렉토리가 등록되어 있으며, path이 구동할 때 찾는 path는 해당 디렉터리들에서 우선적으로 찾게 된다.&amp;nbsp; `append( path_name )`을 사용하여 `sys.path`를 추가해 주는 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1656164767827&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import sys
print(sys.path)&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사실 상, 다음에 소개되는 OS차원의 환경변수인 `$PYTHONPATH`에 추가해주는 것을 python 내부환경에서 처리해 주는 것과 동일하다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3) 환경변수 ( PYTHONPATH)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;OS 차원에서 환경변수 `PYTHONPATH`를 등록해 주는 방법이 있다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;(Windows)&lt;/h4&gt;
&lt;pre id=&quot;code_1656165244888&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;set PYTHONPATH=C:\python-project\path\my_module\&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;(Linux)&lt;/h4&gt;
&lt;pre id=&quot;code_1656165268494&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ export PYTHONPATH='/root/python-projects/path/'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;if __name__=='__main__'의 의미&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;python의 모든 개체는 내부적으로 사용하거나, 초기화에 사용되는 던더(Double Underscore)들이 포함되어 있다. 대표적으로 class의 생성자인 `__init__()`등이 여기에 해당한다. 이중에서, 일반개체외에 최상인 개체인 모듈자체에는 `__name__`이 포함되어 있다. 다음과 같이 실행해 보도록 하자.&lt;/h4&gt;
&lt;pre id=&quot;code_1656166025365&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print( dir() )
# ....(생략) ...  , __name__ , ....(생략)
print( __name__ )
# '__main__'&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;`dir()`을 통해서 현재 최상위 개체에 로딩되어 있는 개체와 변수를 확인 할 수 있다. ( `__name__`이 이미 존재한다. ) `print(__name__)`으로 변수 내용을 출력해 보면, 아마도 대다수의 환경에서는 `__main__`이 출력 될 것이다. `__main__`은 현재 실행되는 위치의 이름을 저장하고 있는 변수이다. 즉, 현재 실행되는 모듈의 환경에 `main`에서 호출되었다는 것이다.&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그렇다면, `main`이외의 다른것이 있다는 것일까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그렇다. __name__의 내용은 크게 2종류 이다.&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최상위 모듈에서 실행&amp;nbsp; : `__main__`&lt;/li&gt;
&lt;li&gt;참조되는 모듈에서 실행 : `모듈 이름`&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실험을 위해서,&amp;nbsp;다음과 같이 `my_module`모듈을 생성하고 my_module.py에 저장하자.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그리고 다른 파일에서 import 해보도록하자.&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1656166485599&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# my_module.py
def add(a,b):
    return a+b

print('my_module : ' , __name__)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1656166537817&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import my_module
print('load a my module')&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어떤 결과가 출력 되었는가?&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1656166703794&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;my_module :  my_module
load a my module&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;응? 프린트 문장이 2개? 왜?&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위 실험 결과에서 이해할 수 있듯이, python은 내부적으로 `import`를 하는 시점에 module 파일이 실행된다. 즉, `my_module`이라는 모듈이 실행될 때 `print`문이 실행 된 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그렇다면, 다시 이런 걱정이 될 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;음.... 그렇다면, `import` 할 때마다 import 내부 실행 결과가 구동되면 어떻게 하지????&quot;&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;위와 같은 문제를 해결하기 위해서, 오직 module 자체를 실행할 때만 동작하는 코드루틴을 만들기 위해서, `if __name__==&quot;__main__&quot; ` 이라는 구문을 사용하는 것다. 이제 우리는 내부 동작을 확실히 이해 할 수 있다. import 할 때는 실행하지 말고, module 자체에서 실행할 때만 &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;( __name__ == '__main__' )&lt;/span&gt; 구동 하도록 조건문을 걸어준 것이다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;파이썬&amp;nbsp; 패키지 (Python Package)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;파이썬 패키지는 모듈들의 묶음이다. 여러 개의 module을 포함하는 디렉터리 구조와 `__init__.py`로 구성 되어 있다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzDHug/btrFLBr5dEi/20Vg8SlCVNnxIySEQbaq5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzDHug/btrFLBr5dEi/20Vg8SlCVNnxIySEQbaq5K/img.png&quot; data-alt=&quot;모듈과 패키지의 관계도.&amp;amp;nbsp;# 출처: pythonstudy.xyz&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzDHug/btrFLBr5dEi/20Vg8SlCVNnxIySEQbaq5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzDHug%2FbtrFLBr5dEi%2F20Vg8SlCVNnxIySEQbaq5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;594&quot; height=&quot;395&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모듈과 패키지의 관계도.&amp;nbsp;# 출처: pythonstudy.xyz&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 연 재 ]&amp;nbsp; (다음편에서...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 이야기/Python</category>
      <category>python module</category>
      <category>Python Package</category>
      <category>sys.path.append</category>
      <category>__name__</category>
      <category>다른 디렉토리 import</category>
      <category>모듈 불러오기</category>
      <category>상대 경로 import</category>
      <category>파이썬 모듈화</category>
      <category>파이썬 패키지</category>
      <category>패키지 불러오기</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/194</guid>
      <comments>https://windflex.tistory.com/194#entry194comment</comments>
      <pubDate>Sat, 25 Jun 2022 23:42:25 +0900</pubDate>
    </item>
    <item>
      <title>Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel</title>
      <link>https://windflex.tistory.com/193</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xCS7I/btrE3yktYmW/ERRoOxQpRZdeDikLKOUOJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xCS7I/btrE3yktYmW/ERRoOxQpRZdeDikLKOUOJ0/img.png&quot; data-alt=&quot;파이썬 가상환경 (Python Virtual Evironment). Conda, Venv, Virtualenv, freeez에 대해서 알아보자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xCS7I/btrE3yktYmW/ERRoOxQpRZdeDikLKOUOJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxCS7I%2FbtrE3yktYmW%2FERRoOxQpRZdeDikLKOUOJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;348&quot; height=&quot;348&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;파이썬 가상환경 (Python Virtual Evironment). Conda, Venv, Virtualenv, freeez에 대해서 알아보자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상환경 생성 관리를 위해 가장 많이 사용되는 툴로써, `conda` , `venv` 등이 있다. 그러나 우리는 환경에 따라서 이들을 사용할 수 없는 환경이 주어지기도 한다. 예를 들면, conda를 지원하지 않는 container 이미지 등에서 작업을 해야 하는 경우이다. 또한 종종 venv가 잘 동작하지 않거나 에러를 발생하는 경우도 있다. 이러한 경우, 기존 python2.x에서 사용하던 추가패키지로 `virtualenv`를 설치하여 사용할 수 있다. 사용하는 방법을 거의 비슷하므로 옵션의 차이 정도만 필요할 때 참조하여 사용하면 되겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOdlZl/btrE4Wj9Awz/JWTkQoeoPI3bC6RfKT9L40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOdlZl/btrE4Wj9Awz/JWTkQoeoPI3bC6RfKT9L40/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp; https://django-easy-tutorial.blogspot.kr/2015/08/python-virtual-environment-setup-in-ubuntu.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOdlZl/btrE4Wj9Awz/JWTkQoeoPI3bC6RfKT9L40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOdlZl%2FbtrE4Wj9Awz%2FJWTkQoeoPI3bC6RfKT9L40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;422&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp; https://django-easy-tutorial.blogspot.kr/2015/08/python-virtual-environment-setup-in-ubuntu.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NBkMf/btrE3HajNtU/km9ekBYXQ5Kiqqj8nT2yw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NBkMf/btrE3HajNtU/km9ekBYXQ5Kiqqj8nT2yw1/img.png&quot; data-alt=&quot;가상환경을 생성하면, 서로 다른 버전과 패키지를 독립적으로 구성이 가능하다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NBkMf/btrE3HajNtU/km9ekBYXQ5Kiqqj8nT2yw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNBkMf%2FbtrE3HajNtU%2Fkm9ekBYXQ5Kiqqj8nT2yw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;773&quot; height=&quot;349&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가상환경을 생성하면, 서로 다른 버전과 패키지를 독립적으로 구성이 가능하다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;1. venv&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Venv Python3의 가상환경을 관리하는 가장 기본이 되는 관리도구이다. Python 2.x에서는 기본지원이 없었는데, python3.x로 변경되면서 python 자체에서 기본지원하도록 기본 패키지화 되었다. 기본 도구인 만큼 알아두면 많은 도움이 된다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;venv 공식 웹페이지&amp;nbsp; : &lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.python.org/3/library/venv.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 구문은 다음과 같다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1655473410647&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python3 -m venv /path/to/new/virtual/environment&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;`/path/tonew/virtual/environment`는 새로운 환경을 생성한 경로와 이름이다. 단순 가상환경의 이름만을 표기하면, 현재 디렉토리의 하위에 해당이름의 디렉토리가 생성된다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상환경은 python의 명령어 및 설정정보를 다른 디렉토리에 설치/복사/생성해 둔 묶음이다. 그리고, 이후에 가상환경으로 변경하면 기본 root_dir을 가상환경의 디렉토리도 임시 변경해 둔것이다. 즉, 추가적인 python version과 하위에 설치된 라이브러리들을 설치해 두고, 시스템에게 python의 기본 실행위치를 속여서 처음부터 python이 이 환경이라고 OS를 인식시키는 것이다. (&lt;span&gt;docker/container도 이와 비슷한 개념에서 출발 했다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로운 디렉토리를 생성하고, 해당 디렉토리에 python 등 필수 패키지를 설치하는 것이 생성과정이며,&lt;/li&gt;
&lt;li&gt;상기 서술한 기본 root_dir을 변경하는 작업들을 수행하는 것이 `activate`이며, 원복하는 것이 `deactivate`이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1655471394174&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python3 -m venv &amp;lt;venv name&amp;gt;

or

python -m venv &amp;lt;venv name&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나, 종종 venv가 잘 동작하지 않는 경우가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;2. conda&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJBN1N/btrE3LYjzT1/VauQtK0xvlQ9Pb6FOqsBE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJBN1N/btrE3LYjzT1/VauQtK0xvlQ9Pb6FOqsBE0/img.png&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;98&quot; data-is-animation=&quot;false&quot; style=&quot;width: 58.5804%; margin-right: 10px;&quot; data-widthpercent=&quot;59.27&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJBN1N/btrE3LYjzT1/VauQtK0xvlQ9Pb6FOqsBE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJBN1N%2FbtrE3LYjzT1%2FVauQtK0xvlQ9Pb6FOqsBE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;307&quot; height=&quot;98&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n8E3s/btrE3TO7or6/H2gf9DAc3lKkmDj1vCtH1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n8E3s/btrE3TO7or6/H2gf9DAc3lKkmDj1vCtH1k/img.png&quot; data-origin-width=&quot;310&quot; data-origin-height=&quot;144&quot; data-is-animation=&quot;false&quot; style=&quot;width: 40.2568%;&quot; data-widthpercent=&quot;40.73&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n8E3s/btrE3TO7or6/H2gf9DAc3lKkmDj1vCtH1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn8E3s%2FbtrE3TO7or6%2FH2gf9DAc3lKkmDj1vCtH1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;310&quot; height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;conda create를 통한 가상환경 생성/관리. venv 대비 상대적으로 관리가 쉽다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;conda 설치방법은 아래 펼치는 글&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. conda 설치파일 다운로드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 사이트 URL을 접속하여 설치하고자 하는 버전에 맞게 다운로드 받는다. 예를 들면, Linux의 경우 다음과 같이 wget을 통해서 다운로드 받으면 편할 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`$ wget &lt;a href=&quot;https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh&lt;/a&gt;`&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 설치파일 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드 받은 설치 파일을 실행해 주자. Linux는 다음과 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`$ bash Anaconda3-2022.05-Linux-x86_64.sh`&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 환경 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료되었다면, 환경파일 PATH로 등록하여 사용하기 쉽게 만들어 주자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`$ export PATH=~/anaconda3/bin:~/anaconda3/condabin:$PATH`&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 PATH를 실행하기 귀찮다면, 실행 시 시작될 수 있도록 ~/.bashrc의 마지막에 위의 코드를 삽입하고/저장한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`$ nano ~/.bashrc` --&amp;gt; 마지막 라인에 위 export ... 삽입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 패키지 설치 및 가상환경 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`$ conda install cudnn`&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*가상환경 관리는 아래 내용 참조&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;conda를 통해서 패키지를 관리하는 경우라면, 가상환경에 대한 관리도 conda를 사용하는 것이 가장 쉬운 편이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상환경 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1655474730057&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda create -n new_env python=3.7&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;구문 형식 : conda create -n &amp;lt;환경명&amp;gt; python=&amp;lt;버전(ex:3.5이나 3.7 등)&amp;gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상환경으로 변경 (가상환경으로 진입)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1655474914907&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda activate new_env
    or
activate new_env&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원래 환경으로 복귀 (가상환경에서 나옴)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1655474993441&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda deactivate
      or
deactivate&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;패키지 설치 (가상환경으로 진입 후)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1655475113819&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda install pandas
    or
pip install pandas&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설치된 패키지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1655474856617&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda env list&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;conda 는 pip등에서 관리하지 않는 패키지도 관리해 준다. 이 때문에 python 자체가 아니더라도 관련된 환경/설치 파일을 동시에 설치 할 수 있다. 대표적으로, GPU 관련된 CUDA toolkit, cuDNN등도 conda를 사용하여 설치할 수 있다.&amp;nbsp; (대박~!)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AQdUE/btrFkv63X9A/MIsBiVCSW20gRl9rCf1f6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AQdUE/btrFkv63X9A/MIsBiVCSW20gRl9rCf1f6k/img.png&quot; data-alt=&quot;conda install cuDNN 실행하면 다음과 같이 최신 cuda와 cudnn을 한번에 설치할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AQdUE/btrFkv63X9A/MIsBiVCSW20gRl9rCf1f6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAQdUE%2FbtrFkv63X9A%2FMIsBiVCSW20gRl9rCf1f6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;510&quot; height=&quot;324&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;conda install cuDNN 실행하면 다음과 같이 최신 cuda와 cudnn을 한번에 설치할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나, conda를 지원하지 않는 경우도 다수 존재하며, conda에서는 설치할 수 없는 패키지들도 존재하기 때문에 가급적, venv와 다음에서 설명할 virtualenv도 함께 숙지해 두면 좋을 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;3. virtualenv&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SkqrU/btrE4H1TN22/KImzRzByw8heHPum3yy5r0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SkqrU/btrE4H1TN22/KImzRzByw8heHPum3yy5r0/img.png&quot; data-alt=&quot;python virtualenv 가상환경 관리자&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SkqrU/btrE4H1TN22/KImzRzByw8heHPum3yy5r0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSkqrU%2FbtrE4H1TN22%2FKImzRzByw8heHPum3yy5r0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;371&quot; height=&quot;136&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;python virtualenv 가상환경 관리자&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`venv`가 에러가 발생하는 경우&amp;nbsp;virtualenv를 사용하자&lt;/p&gt;
&lt;pre id=&quot;code_1655471409844&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python -m virtualenv &amp;lt;venv name&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;virtualenv가 설치되어 있지 않다면, pip 로 설치해 주자. `pip install virtualenv`&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;virtual env를 생성하였다면, 사용하는 환경을 새로운 환경 `new_env`로 변경해 주자.&lt;/p&gt;
&lt;pre id=&quot;code_1655471516730&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;source new_env/bin/activate&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;새로운 버추얼 환경의 이름이 `new_env`인 경우이다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 virtual env 환경에서 필요한 패키지를 설치해 주자. 다음은 tensorflow를 설치하는 예이다.&lt;/p&gt;
&lt;pre id=&quot;code_1655471554889&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install tensorflow==2.4.1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 모두 완료 되었다면, 새로운 환경에서 빠져나온다.&lt;/p&gt;
&lt;pre id=&quot;code_1655471656418&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;deactivate&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;pip freeze&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 사용하는 library들을 고정하고, 리스트를 `requirements.txt`로 내보낸다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1655472787845&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip freeze -l &amp;gt; requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내보내진 requirements.txt는 이후 아래와 같은 명령어로 일괄 설치가 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1655473018872&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install -r requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;`-r`옵션은 `--requirement`의 축약 버전이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 requirements.txt의 예시이다. requirements.txt에는 다음과 같이 필요할 패키지와 버전이 명시되어 있다. 이러한 정보를 이용하여 명확하게 동일한 설치환경을 구축하고자 하는 것이 가상환경을 관리하는 목적이라 하겠다.&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;llvmlite==0.36.0&lt;br /&gt;matplotlib==3.4.2&lt;br /&gt;numba==0.53.1&lt;br /&gt;numpy==1.20.3&lt;br /&gt;scikit-learn==0.24.2&lt;br /&gt;scipy==1.7.0&lt;br /&gt;sklearn==0.0&lt;br /&gt;timm==0.4.5&lt;br /&gt;torch==1.9.0&lt;br /&gt;torchaudio==0.9.0&lt;br /&gt;wget==3.2&lt;br /&gt;zipp==3.4.1&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;4. ipykernel - J&lt;span&gt;&lt;b&gt;upyter Notebook커널로 등록하자&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 새로운 환경을 Jupyter Notebook 또는 Jupyter Lab에서 Kernel로 등록하고자 하는 경우, `ipykernel`을 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1655471754177&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install ipykernel
python -m ipykernel install --user --name new_env --display-name new_env_kernel&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;ipykernel 명령어는 다음과 같은 유형이다:&amp;nbsp; &amp;nbsp;`ipykernel install --user --name &amp;lt;venv_name&amp;gt; --display-name &amp;lt;표시할 이름&amp;gt;&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1658134214367&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;jupyter kernelspec uninstall 가상환경이름
ex) jupyter kernelspec uninstall python-ml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[관련 글]&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Conda-Jupyter] Conda 가상환경과 Jupyter Kernel 연동/생성/삭제&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/212&quot;&gt;2022.12.06 - [개발 이야기/Python] - [Jupyter Kernel 추가] conda 가상환경을 jupyter Kernel로 추가하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/207&quot;&gt;2022.09.19 - [개발 이야기/Python] - [주피터노트북 커널] jupyter lab/notebook kernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/193&quot;&gt;2022.06.17 - [분류 전체보기] - Python 가상 환경 관리 4종 - venv / virtualenv / ipykernel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/126&quot;&gt;2020.06.04 - [개발 이야기/Python] - [파이썬] Anaconda x Jupyter notebook 설치 및 설정 방법 - 가상환경으로 파이썬 개발환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/19&quot;&gt;2020.03.10 - [IT 이야기] - Python x Jupyter Notebook 설치 및 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://richwind.co.kr/206&quot;&gt;2022.09.19 - [IT 이야기/IT 상식] - [Python 가상환경] conda 설치 및 가상환경 (feat. 내부 로직 &amp;amp; cheat sheet)&lt;/a&gt;&lt;/p&gt;</description>
      <category>conda</category>
      <category>conda create</category>
      <category>ipykernel</category>
      <category>python venv</category>
      <category>python virtualenv</category>
      <category>python 가상환경</category>
      <category>venv</category>
      <category>virtualenv</category>
      <category>가상환경 생성</category>
      <category>파이썬 가상환경 생성</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/193</guid>
      <comments>https://windflex.tistory.com/193#entry193comment</comments>
      <pubDate>Fri, 17 Jun 2022 22:37:49 +0900</pubDate>
    </item>
    <item>
      <title>[librosa 설치] 설치오류 - sndfile library not found</title>
      <link>https://windflex.tistory.com/191</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA1MVA/btrDVoo2boe/K6qZdqkfl3OOGQyWaP7Xv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA1MVA/btrDVoo2boe/K6qZdqkfl3OOGQyWaP7Xv0/img.png&quot; data-alt=&quot;Librosa 설치 오류 및 soundfile library not found Error&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA1MVA/btrDVoo2boe/K6qZdqkfl3OOGQyWaP7Xv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA1MVA%2FbtrDVoo2boe%2FK6qZdqkfl3OOGQyWaP7Xv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;322&quot; height=&quot;322&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Librosa 설치 오류 및 soundfile library not found Error&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;librosa 설치 오류&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Librosa를 처음 설치하다 보면, 아래와 같이 import도 되지 않는 상황이 종종 발생하곤 한다. &lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;아무리, pip 명령어를 만져봐도 시작부터 되지 않는 경우이다.&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;sndfile library not found&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;librosa는 내부적으로, scipy.wavefile과 sounfile 라이브러리를 사용하는데, soundfile 라이브러리 설치가 잘 안되서 발생하는 문제이다. soundfile library는 파이썬 외에 os차원에서 설치해야하는 library가 포함되어 있기 때문에, pip 및 종속성검사로 설치가 되지 않는다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZiTaa/btrDKItoipo/dszDKDOPkaSaGQ7Y2X97p0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZiTaa/btrDKItoipo/dszDKDOPkaSaGQ7Y2X97p0/img.png&quot; data-alt=&quot;&amp;quot;sndfile library not found&amp;quot;에러가 뜨면서 librosa가 import도 되지 않는다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZiTaa/btrDKItoipo/dszDKDOPkaSaGQ7Y2X97p0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZiTaa%2FbtrDKItoipo%2FdszDKDOPkaSaGQ7Y2X97p0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;651&quot; height=&quot;568&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&quot;sndfile library not found&quot;에러가 뜨면서 librosa가 import도 되지 않는다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Librosa 공식웹페이지 이외, Github Page를 참조하면, Soundfile을 설치할 때 다음과 같은 사전설치/업데이트가 필요하다고 가이드 되어 있다. (놓치기 쉽다. 그냥 `pip install librosa` 하기 때문)&lt;/p&gt;
&lt;pre id=&quot;code_1655828993888&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apt-get install ffmpeg   # Linux&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는,&lt;/p&gt;
&lt;pre id=&quot;code_1655829040338&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apt-get install gstreamer1.0-plugins-base gstreamer1.0-plugins-ugly&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;MacOS의 경우&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1655829097098&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install ffmpeg
   혹은
brew install gstreamer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Conda를 사용하는 경우,&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1655829214772&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda install -c conda-forge ffmpeg
conda install -c conda-forge librosa&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;conda 가 지원하는 환경이라면, conda 최고~~~!!!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, 이렇게 해 주어도 안되는 경우가 있다. 그렇다면 아래와 같이 해 주자.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f89009;&quot;&gt;soundfile library를 다시 설치 해 주자.&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1654139565742&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install -y libsndfile1-dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간혹 설치 완료 후에도 여전히 에러가 발생하는 경우가 있는 Notebook을 재시작 해주면 해결 된다. ^^;&lt;/p&gt;</description>
      <category>개발 이야기/Python</category>
      <category>librosa</category>
      <category>librosa import error</category>
      <category>librosa 설치 오류</category>
      <category>libsndfile</category>
      <category>OSError</category>
      <category>sndfile not found</category>
      <category>Soundfile</category>
      <category>soundfile library</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/191</guid>
      <comments>https://windflex.tistory.com/191#entry191comment</comments>
      <pubDate>Thu, 2 Jun 2022 15:56:22 +0900</pubDate>
    </item>
    <item>
      <title>차원 축소 (Dimensional Reduction) 설명하는 그림</title>
      <link>https://windflex.tistory.com/189</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;차원축소 및 프로젝션에 대해 한번에 이해할 만한 이미지&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PCA (Principal Component Analysis) 등 Dimesional Reduction 의 개념을 이해하는데 도움이 되는 그림을 소개 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중앙에 있는 코일 같은 신호가 Original Data라면, 한쪽의 축으로 프로젝션한 결과 데이터 X축/Y축 프로젝션 데이터 각각이 Dimentional Reduction의 결과물 이라고 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PCA와 같은 경우는 이러한 X,Y축을 고정하지 않고, Varianace (변별력)가 가장 큰 축을 찾아서 프로젝션 하는것이 차이가 있다 하겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VYKS7/btrC0QzakI0/uWxWf5sI8wnKhax6nZlK71/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VYKS7/btrC0QzakI0/uWxWf5sI8wnKhax6nZlK71/img.gif&quot; data-alt=&quot;Dimensional Reduction, Data Projection. 출처 : imgur&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VYKS7/btrC0QzakI0/uWxWf5sI8wnKhax6nZlK71/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/VYKS7/btrC0QzakI0/uWxWf5sI8wnKhax6nZlK71/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;532&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Dimensional Reduction, Data Projection. 출처 : imgur&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기</category>
      <category>Dimensional Reduction</category>
      <category>pca</category>
      <category>Principal Component Analysis</category>
      <category>projection</category>
      <category>데이터 공간</category>
      <category>데이터 스페이스</category>
      <category>차원축소</category>
      <category>프로젝션</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/189</guid>
      <comments>https://windflex.tistory.com/189#entry189comment</comments>
      <pubDate>Tue, 24 May 2022 14:07:02 +0900</pubDate>
    </item>
    <item>
      <title>[ 인터뷰 후기 ] 몰로코 코딩테스트 및 인터뷰 후기</title>
      <link>https://windflex.tistory.com/188</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;업계를 뜨겁게 달구고 있는 몰로코 (MOLOCO) 채용에 지원을 했었다.&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;303&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dRxB41/btrCVO3TVGf/TYnJm1QwYyHUly5t3TwSWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dRxB41/btrCVO3TVGf/TYnJm1QwYyHUly5t3TwSWK/img.png&quot; data-alt=&quot;몰로코 코딩테스트 및 인터뷰 후기, 리뷰&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dRxB41/btrCVO3TVGf/TYnJm1QwYyHUly5t3TwSWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdRxB41%2FbtrCVO3TVGf%2FTYnJm1QwYyHUly5t3TwSWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1013&quot; height=&quot;303&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;303&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;몰로코 코딩테스트 및 인터뷰 후기, 리뷰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;요즈음 처럼 개발자 수요가 증가한 경우를 보지 못했었다. 이러한 경향을 맞추어 2021~2022년 개발자들 이직 바람이 불고있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;현 직장에 거의 불만은 없다. 아니 오히려 TOP급이기 때문에 딱히 어딜 가고 싶지도 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나, 이직 바람으로 마음이 조금 들뜨더라..&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나도 이직 할 때가 된것인가?&lt;br /&gt;평소에 이직을 선호하는 기업이 있지는 않았기 때문에 고민을 해 보았다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;고민 후 객관적으로 선호되는 기업은 나스닥의 FAANG, 그리고 몰.두.센&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;FAANG 중에서, Facebook(Meta)는 캐나다/미국쪽에 기회가 있었지만 영어 장벽으로 패스 했다. 그리고, 개인적으로 대한민국에서 살고 싶다. Amazon 은 업무강도가 쎈것으로 유명해서 패스, Apple 은 정말 좋은 기업이지만 Apple Korea는&amp;nbsp; (개발/연구 직군) 평이 그다지 좋지 않더라.. 등등&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이것 저것 조건을 제외하고 남은 것이, Google Korea와 몰.두.센.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Google Korea는 아직 관련된 오픈된 포지션을 찾지 못했고,&amp;nbsp;두나무와 센드버드는 현재 오픈된 포지션들이 현재 업무와 약간의 미스매칭이 있었다. 결과적으로 몰로코 (Moloco)가 가장 적합하다는 결론을 지었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또한, 아래와 같이 현재 투자규모로 볼 때, Series C 투자를 받았고, 현재 총 투자유지 2119억이라고 한다. (22.5월 기준). 투자사들 또한 메이져 투자사로 멀지 않은 미래에 엑싯을 할 수 있을 것으로 기대 된다. 따라서, 현 시점에서 몰로코에 조인하게 되면 가장 짧은 시간에 가장 효율적인 직무와 투자 효과까지 얻을 수 있다는 판단이 섰다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQnm47/btrC0P72pWj/UxN12vpDv07IKzLEFGdzf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQnm47/btrC0P72pWj/UxN12vpDv07IKzLEFGdzf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQnm47/btrC0P72pWj/UxN12vpDv07IKzLEFGdzf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQnm47%2FbtrC0P72pWj%2FUxN12vpDv07IKzLEFGdzf0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;986&quot; height=&quot;446&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;별 다른 준비도 없이 일단 포지션에 지원을 했다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;정말 무식하면 용감하긴 하다.&lt;br /&gt;이렇게 입사 난이도가 힘든 곳인지 몰랐다.&lt;/blockquote&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;채용 프로세스&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몰로코의 채용 프로세스는 매우 까다롭더라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 단계 들이 있다. 참 길~~~었다. 참고로 결론부터 이야기 하면 필자는 최종 프로세스까지 진행 후 탈락 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 업무 영역과 포지션이므로, 다른 포지션의 경우 다소 맞지 않을 수 도 있을 것 같으니, 이점 참조 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;이력서 (서류)&lt;/li&gt;
&lt;li&gt;리크루터 폰 스크리닝&lt;/li&gt;
&lt;li&gt;코딩테스트&lt;/li&gt;
&lt;li&gt;1차 인터뷰 (실무 면접)&lt;/li&gt;
&lt;li&gt;인터뷰 1 : 실시간 코딩 인터뷰&lt;/li&gt;
&lt;li&gt;인터뷰&amp;nbsp;2 : 시니어 직무 면접 ( 수학적 이론 중심 )&lt;/li&gt;
&lt;li&gt;인터뷰&amp;nbsp;3 : 시니어 직무 면접 ( 케이스 제시, 문제해결 테일러링 )&lt;/li&gt;
&lt;li&gt;최종 결과 통보 : 합/불&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몰로코 블로그에 의하면, 인터뷰 1 + 인터뷰 2 + 인터뷰 3은 만장일치일 경우에만 최종 합격 통보로 처리한다고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;이력서 / 폰스크리닝&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이력서는 영문/한글이 있는데, 딱히 영문이력서로 제출해야 한다는 Requirement가 없었기 때문에 한글로 입력 했다. 나중에 리크루터와 이야기 할 때, 주로 영문으로 작성한다는 이야기를 들었다. 영문으로 다시 제출하겠다는 의견을 이야기 했었지만, 필요하면 요청하겠다고 해서 한글 이력서로 유지 했다. 이후 영문 재작성은 하지 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이후에 인터뷰 대상인 외국인도 있었는데, 어떻게 이력서를 봤는지 모르겠다. 물어보니 이력서 내용을 알고 있긴 하더라...&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그냥 닥치고 영어로 작성하는게 좋을듯 하다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;포스크리닝은, 짠밥인 짠밥인지라.. 뭐.. 그냥 이야기 했다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;코딩 테스트&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Moloco의 코딩테스트는 &quot;코드시그널&quot; 이라는 사이트에서 진행 되었다. (&lt;a href=&quot;https://codesignal.com/&quot;&gt;https://codesignal.com/&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실리콘벨리 쪽에서는 많이 사용하는 플랫폼인것 같다. 장기적으로 실리콘벨리가 지향점이라면 익숙해 지는 것이 좋을 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1219&quot; data-origin-height=&quot;688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RT0qL/btrCVPPhJDt/af2jYSx3TXQK39yQH8dRn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RT0qL/btrCVPPhJDt/af2jYSx3TXQK39yQH8dRn0/img.png&quot; data-alt=&quot;코드시그널 스크린샷 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RT0qL/btrCVPPhJDt/af2jYSx3TXQK39yQH8dRn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRT0qL%2FbtrCVPPhJDt%2Faf2jYSx3TXQK39yQH8dRn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1219&quot; height=&quot;688&quot; data-origin-width=&quot;1219&quot; data-origin-height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드시그널 스크린샷 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;275&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deFFP0/btrCXml4CDi/xBcK9UbtRhRea0p2l4RMGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deFFP0/btrCXml4CDi/xBcK9UbtRhRea0p2l4RMGk/img.png&quot; data-alt=&quot;코드시그널을 사용하여 코딩테스트를 진행하는 기업&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deFFP0/btrCXml4CDi/xBcK9UbtRhRea0p2l4RMGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeFFP0%2FbtrCXml4CDi%2FxBcK9UbtRhRea0p2l4RMGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1100&quot; height=&quot;275&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;275&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드시그널을 사용하여 코딩테스트를 진행하는 기업&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;필자가 지원한 포지션은 SWE가 아니었기 때문인지 알고리즘 심화 문제가 주어지진 않았다. 필자의 경우, 알고리즘 보다는 실제 개발 중에 필요한 기능구현성 문제가 출제 되었다. 따라서, 알고리즘 구현보다는 문제를 이해하고 그에 맞게 구현을 해야 했다. 여기에서 문제 자체가 구현항목/제한사항 등이 다수개여서 문제를 정확하게 이해하는데 시간이 더 오래 걸린듯 하다. 총 4문제가 주어지고 70분이 제공되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;결과적으로, 필자는 시간이 모자라서 마지막 문제를 최종까지 완료하지는 못했다. 문제 자체는 어렵지 않았다. 5분이 남아있을 때 부터 코드가 수정되지는 않았는데, 아마도 구현은 60분, 10분은 정리하라는 의미인듯 하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;다시 시험을 보게 된다면, 알고리즘 보다는 기능을 얼마나 빠르고 정확하게 구현하는지에 초점을 두어야 겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;마지막 문제를 다 풀지 못했기 때문에, 탈락할 지도 모른다는 생각을 하고 있었는데, 약 3~4일 후쯤 인터뷰 일정 조율 연락이 왔다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;인터뷰 - 1&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1차 인터뷰는 한국에 근무하는 실무자 인터뷰 였다. 해당 포지션은 한국에 근무하는 동료가 많지 않았다고 한다. 한국에서 동료가 될 분들중 선별된 분과 이야기를 할 수 있었다. 대부분 본인의 과거 진행했던 프로젝트와 현재 진행중인 프로젝트를 설명하였다. 또한, MOLOCO 내부에서 주로 다루고 있는 문제에 관련하여 케이스를 제시하고 어떻게 해결할 것인지.. 질의/응답하게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;사실, 1차 인터뷰는 평이한 수준이었다.&lt;br /&gt;1차 인터뷰로써는 입사 난이도 &quot;최상&quot;이라는 느낌을 받지는 못했었다.&amp;nbsp;&lt;br /&gt;그러나, 이것은 나만의 착각 이었던것 같다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;시니어 인터뷰 (임원급)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;몰로코는 서로의 평가에 면접관의 판단의 객관성을 유지하기 위해서,&lt;br /&gt;1:N 면접이 아니라. 1:1 면접 N회로 진행한다고 한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1차 인터뷰가 끝나고 다시 1주일 정도 지나서, 2차 인터뷰 일정을 조율 하였다. 연속 3회 일정.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;일정 조율부터 난이도가 급격하게 오르는 느낌이었다. 해당 포지션의 시니어급은 한국에는 없다고 한다. 모두 실리콘벨리.... 일정 잡기가 쉽지 않다. 리크루터와 일정 이메일만 4~5번 주고 받은듯 하다. 결국, 정해진 일정은 아침 8시, 다음날 아침 7시. 끝나고 바로 연이어서 다른 인터뷰 8시... 헉헉...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아침 7시 인터뷰는 너무 빡신거 아닌가?&lt;br /&gt;더군다나, 끝나고 나면 바로 연이어 다른 회의실에서 다른 인터뷰&lt;br /&gt;이 날은 혹 제때 일어나지 못할까봐 새벽 4시에 일어나서 돌아 다녔다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;인터뷰 2 - 실시간 코딩 인터뷰 with 외국인&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2차 인터뷰중 첫번째는, 실시간 코딩 인터뷰이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그런데, 좀 아쉬운것 중 하나는, 필자는 인터뷰 반이 지나도록 해당 인터뷰 시간인 &quot;코딩 인터뷰&quot;인지 몰랐다는 것이다. 인터뷰어가 URL을 제시하고 접속할 때까지 인터뷰 속성을 알지 못했다. 당연히 뭐 준비고 뭐고 마음의 준비도 되어 있지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인터뷰어를 처음 만났을 때 부터 조금 긴장하였다. 왜냐고?&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;외국인 / 영어 (ㅜ_ㅜ)&lt;br /&gt;일단 질문을 들어야하고, 대답할 내용도 생각해야 하고, 어떻게 말해야할지도 영어로.&lt;br /&gt;&lt;/span&gt;이 와중에 인터뷰 중간쯤 지나더니, 갑자기 웹코딩 페이지를 열더라.&amp;nbsp;&lt;br /&gt;코딩 실력과는 별개로, 아~~~ ^^;;;;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;일단 제시되는 문제가 잘 읽히지 않았다. 문제를 알아야 그에 맞는 코드를 작성할 텐데, 실시간으로 같이 보고 있으니, 차분히 문제를 읽어볼 만한 여유가 없었다. 이 때문에 나중에 좀 삽질을 했다.&amp;nbsp;두번째로는, 정작 문제는 아주 쉬웠다. 릿코드 기준 이지~미디엄. 프로그래머스 기준 Lv.2 정도 수준. 그러나, 그게 외국인이 같이 보면서 코드를 짜니깐 잘 되질 않더라. 이러한 환경이 익숙한 사람은 괜찮을듯 하다.&amp;nbsp;필자의 경우, 미리 짜 놓은 코드를 코드리뷰하는 것은 익숙해도, 실시간으로 화면에서 문제를 이해하고 작성하는 것은 익숙치가 않다. 앞으로도 익숙해질지 의문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;인터뷰 3 - Theory&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아침 7시부터 진행되는 인터뷰 였다. 혹시나 제 시간에 접속하지 못할까봐 긴장되었는데, 그날은 새벽 4시에 눈을 뜨게 되었다. 인터뷰어도 바로 다음 인터뷰가 있는 것을 알고 있기에 바로 본론으로 들어갔다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기 수행 프로젝트 설명&lt;/li&gt;
&lt;li&gt;기 수행 프로젝트에서 질의/응답. 몰로코에서 하는 업무와 관련해서 연계 질문&lt;/li&gt;
&lt;li&gt;케이스 및 환경 제시 문제 : 해결방안, 그 방법으로 진행했을 때의 변화 (Before / After 차이)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;답변하는 것에 맞추어 이론적 배경 : 수학적으로 Define하여 설명. 수식으로 설명. 수식으로 증명( 요건 못해서 포기 )&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;잠도 제대로 못 깬것 같은데, 갑자기 수식을 정의해서 차이를 비교해 보라 하더라... 흐음 ^^;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;지나고 나서 보니, 정말 어려운 것도 아니었는데... 라는 생각이 다시 들더라.&amp;nbsp; 아마도 답이 틀려서 수학적 정의 이야기가 나왔지 싶다. 지금 생각해 보면 계속 꼬리에 무는 질문으로 핀치에 몰려서 않좋은 답을 했던 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아무튼, 인터뷰어가 수학과를 나온 사람인듯 하여 대부분의 문제 정의를 수학적으로 제시하기를 원했다. 필자도 수학을 좋아하는 사람중 하나였는데, 기업에서 오랫동안 수학정의를 하지는 않았던 터라 갑자기 훅 치고 들어온 Stanford 수학과 출신에게는 한방 먹을 수 밖에...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;조금 억울해서 끝나고 다시 생각해 보니 별거 아니긴 했는데 ㅜ_ㅜ&amp;nbsp;&lt;br /&gt;바이~바이~&lt;/span&gt;&lt;/blockquote&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;인터뷰 3 - Head급&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인터뷰어는 CTO외 최상위 Head 급 메니저이셨다. 역시 몰로코쯤 되니 최상위 메니저도 인성면접 같은것이 아니더라. 경험을 기반으로 한 질문이 들어오는데 경시할 수 가 없다. 현업에서 사용하는 다양한 경험과 그 속에서 들어오는 질문은 실제 업무경험과 실력을 판별하는데 적절한 질문/응답을 요구 하고 있다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;인터뷰어들은 상당히 훌륭하다고 생각된다.&lt;br /&gt;단지 필자가 적절한 응답을 하지 못했을 뿐이다.&amp;nbsp;&lt;br /&gt;한번 꼬여 들어가니, 나중에는 정신 차리지 못하게 되더라.&lt;br /&gt;인성면접 이런것은 이럴일이 없겠지만, 꼬리에 꼬리를 무는 기술 인터뷰는 대략 난감 ^^;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;총평&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;몰로코에 채용 프로세스를 진행하고 나서 오히려 몰로코에 대한 인식이 더욱 좋아 졌다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코딩테스트는 단지 무조건적 알고리즘 테스트를 하는것이 아니라, 포지션에 맞게 업무에서 요구하는 스킬을 점검하는 것이 좋을것이라고 생각하고, 몰로코의 코딩테스트는 이점에 좀 더 포커스 하고 있는 듯한 느낌이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인터뷰 1차는 스크리닝의 느낌이었다. 최종 임원/시니어급 인터뷰 전에 같이 일할 동료들이 한번 점검하는것 같다. 여기에서 탈락이면 뭐~ 그 이후는 볼것도 없다는 것 이겠지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인터뷰 2차 x 3회는 호불호가 좀 있다. 실시간 코딩 인터뷰 + 영어는 필자가 좀 익숙해져야 할 필요가 있겠다. 구글 코딩테스트도 아마 비슷하게 진행된다고 하니, 실력을 떠나서 순발력을 좀 키워야하지 싶다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;단, 하나 아쉬운점.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;시니어 면접이라서 그런지는 몰라도.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;난해한 질문의 대부분이 몰로코 업무에 사용하는 질문이다. 무슨말이냐고?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;필자의 기술 영역 (다른 영역도 마찮가지 이겠지만) 은 매우 넓다. 따라서, 해당 업무 (광고/타겟마케팅 비즈니스) 문제를 풀어본 경험이 없다면, 즉답은 어려울 가능성이 높다는 것이다. 문제를 인식하여 논문/기술 연구를 할 수 있는 기반은 갖추었을 지언정, 해당 영역이 논문 주제이거나 동일한 문제를 풀어보지 않고서는 이렇게 Deep하게 제시한 문제를 즉답으로 풀기는 쉽지 않을것 같다.&amp;nbsp;물론, 몰로코에서 &quot;이미 타겟마케팅의 해결이 가능한 사람&quot;을 채용을 원하는 경우라면 할말 없지만 말이다. 필자도 면접이 끝나고 조사해 보니 쉽게 풀수 있는 문제였지만, 인터뷰의 실시간 타임에는 기존 수행이력이 있지 않다면 두루뭉실하게 알법한 내용이었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음에도 기회가 주어지면, 이미 느낀점으로 보완 할 수 있겠다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;다음 지원도 가능하려나???&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이야기</category>
      <category>Moloco</category>
      <category>몰로코</category>
      <category>몰로코 채용 프로세스</category>
      <category>몰로코 코딩인터뷰</category>
      <category>몰로코 코딩테스트</category>
      <category>스타트업</category>
      <category>스타트업 채용</category>
      <category>실리콘벨리</category>
      <category>인터뷰 후기</category>
      <category>코딩테스트 후기</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/188</guid>
      <comments>https://windflex.tistory.com/188#entry188comment</comments>
      <pubDate>Tue, 24 May 2022 14:04:48 +0900</pubDate>
    </item>
    <item>
      <title>[코딩 테스트] 파이썬 코딩테스트 핵심 요약 (CheatSheet) - 코테 1시간전에 꼭 보자.</title>
      <link>https://windflex.tistory.com/187</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2344&quot; data-origin-height=&quot;1132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uUkbu/btrC18M3QJa/Te8yefxUZe1iee2jTHgYV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uUkbu/btrC18M3QJa/Te8yefxUZe1iee2jTHgYV0/img.png&quot; data-alt=&quot;코딩테스트를 위한 컨닝페이퍼. Python Coding Test 시 유용한 자료구조 요약 및 활용 사례&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uUkbu/btrC18M3QJa/Te8yefxUZe1iee2jTHgYV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuUkbu%2FbtrC18M3QJa%2FTe8yefxUZe1iee2jTHgYV0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2344&quot; height=&quot;1132&quot; data-origin-width=&quot;2344&quot; data-origin-height=&quot;1132&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코딩테스트를 위한 컨닝페이퍼. Python Coding Test 시 유용한 자료구조 요약 및 활용 사례&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;자꾸만 망각하게 되는 코딩테스트 유형들. 자료구조 기준으로 요약을 정리하고, 활용 사례 및 예제를 정리해 보자. 코딩테스트 하루 전에 숙지해야할 내용들을 정리해 본다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;해시 (Hash)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Key-Value 쌍을 이용한 빠른 탐색&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;해시를 사용하는 대표적인 자료구조는 Dictionary 이다. 키-값 (Key-Value)를 사용하여 자료를 저장하는 해시(Hash) 중에서 Python에서는 Ditionary를 편하게 다루기 위해서 `Counter`, `defaultdict` 등의 라이브러리를 제공한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다음은 주어진 `단어배열` (Array of Words)에서 각 단어의 수를 세는 예제이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Counter()를 이용하면 아래와 같이 단순히 `Counter(array): --&amp;gt; dict`로 그 수를 세어 저장할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[ Counter ]&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372936&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import Counter
input_val = [&quot;Hello&quot;, &quot;World&quot;, &quot;Python&quot;, &quot;Hello&quot;, &quot;Code&quot;, &quot;Test&quot;, &quot;with&quot;, &quot;Python&quot;]
a = Counter(input_val)
print(a)
# Counter({'Code': 1, 'Hello': 2, 'Python': 2, 'Test': 1, 'World': 1, 'with': 1})&lt;/code&gt;&lt;/pre&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Counter() 는 Dictionary로써 뿐만 아니라 산술연산을 지원한다. 따라서 동일한 Key에 대한 산술이 가능하므로, 아래와 같이 Key값의 빈도수에 대한 차이를 `a-b`만으로 구할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372937&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import Counter
input_val = [&quot;Hello&quot;, &quot;World&quot;, &quot;Python&quot;, &quot;Hello&quot;, &quot;Code&quot;, &quot;Test&quot;, &quot;with&quot;, &quot;Python&quot;]
a, b = Counter(input_val), Counter(input_val[:4])
print(a-b)
# Counter({'Python': 1, 'Code': 1, 'Test': 1, 'with': 1})&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[ defaultdict ]&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;경우에 따라서는 `Counter()`가 아니락 직접 dictionary를 다루어야 할 때가 있다. 이 경우, dictionary를 생성하여 value를 계산하는데, 기본적으로 dictionary는 type이 지정되지 않기 때문에 `키-값 셋` (Key-Value 셋)의 초기화가 되어 있지 않다. 위처럼 단어수를 세는 예제의 경우 아래처럼 단순히 덧셈(Add)를 하여 처리 할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372943&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import defaultdict
input_val = [&quot;Hello&quot;, &quot;World&quot;, &quot;Python&quot;, &quot;Hello&quot;, &quot;Code&quot;, &quot;Test&quot;, &quot;with&quot;, &quot;Python&quot;]
d = defaultdict(int)
for w in input_val:
  d[w] = d[w]+1
print(d)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;defaultdict를 사용하지 않고 Key값에 대한 초기화 없이 `dictionary[key]`를 사용하면 `Key Error`를 발생하게 될것이다.&amp;nbsp; 이러한 경우 값이 없는 경우 초기화 해주는 코드를 추가해 주어야 하는데, defaultdict는 이 과정을 내부처리하도록 dictionary를 Class화 해둔 것이다. 편의성을 높이고, 에러발생율을 줄일 수 있다.&amp;nbsp;&lt;/blockquote&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 초기화 없이 dictionary에 수치 연산을 사용할 경우이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372944&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;input_val = [&quot;Hello&quot;, &quot;World&quot;, &quot;Python&quot;, &quot;Hello&quot;, &quot;Code&quot;, &quot;Test&quot;, &quot;with&quot;, &quot;Python&quot;]
d = dict()
for w in input_val:
  d[w] = d[w]+1
print(d)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
&amp;lt;ipython-input-6-3c2a402366b9&amp;gt; in &amp;lt;module&amp;gt;()
      2 d = dict()
      3 for w in input_val:
----&amp;gt; 4   d[w] = d[w]+1
      5 print(d)

KeyError: 'Hello'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[ No Library ]&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;만약 collection library들을 사용할 수 없고, 순수 Python만을 사용해야 한다면 다음과 같이 초기화 처리를 해 주어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372944&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;input_val = [&quot;Hello&quot;, &quot;World&quot;, &quot;Python&quot;, &quot;Hello&quot;, &quot;Code&quot;, &quot;Test&quot;, &quot;with&quot;, &quot;Python&quot;]
d = dict()
for w in input_val:
  d[w] = d[w]+1 if w in d.keys() else 1
print(d)
# {'Hello': 2, 'World': 1, 'Python': 2, 'Code': 1, 'Test': 1, 'with': 1}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;딕셔너리(Dictionary)는 Key들의 순서가 없기 때문에 Index로 접근할 수 없다. Key로만 접근 할 수 있기 때문에, dict.keys()를 사용해서 전체 Key값을 List화 할 수 있다. 그러나, 어느 문서에서는 `dict.keys()`를 사용하지 말고, [w for w in d] 형태를 사용할것을 권고하기도 한다. dict.keys() 대신 dict변수이름 자체를 사용하면 key값을 반환한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나 위 예제에서 `w in d.keys()`는 list로 변환한다. 이 이야기는 해시의 장점인 Key-Search를 사용하지 않고 Full Search를 사용했다는 이야기가 된다. 즉 복잡도 O(n)이 추가 되는 과정이므로 위 전체 연산은 O(n^2)이 되어 버린다. 해시를 사용한 의미가 없다. 따라서, 위와 같은 예제는 해시의 키 값을 바로 사용하도록 아래와 같이 수정되어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372945&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Hash의 Key 초기화 : w in d.keys() ==&amp;gt; List로 변경되기 때문에 Hash Key Search를 사용하지 못하는 예
input_val = [&quot;Hello&quot;, &quot;World&quot;, &quot;Python&quot;, &quot;Hello&quot;, &quot;Code&quot;, &quot;Test&quot;, &quot;with&quot;, &quot;Python&quot;]
d = dict()
for w in input_val:
  d[w] = d[w]+1 if w in d else 1
print(d)
# {'Hello': 2, 'World': 1, 'Python': 2, 'Code': 1, 'Test': 1, 'with': 1}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;line 5 :&amp;nbsp; `d[w] = d[w]+1 if w in d else 1` 으로 Hash Key 사용. 전체 Full Search 보다는 복잡도 감소&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;dict.get()&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;해시 키를 검사하는 `w in d` 와 유사하게, dictionary의 함수 get()을 활용할 수도 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372946&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Hash의 Key 초기화 : dict.get() 사용
input_val = [&quot;Hello&quot;, &quot;World&quot;, &quot;Python&quot;, &quot;Hello&quot;, &quot;Code&quot;, &quot;Test&quot;, &quot;with&quot;, &quot;Python&quot;]
d = dict()
for w in input_val:
  d[w] = d.get(w,0)+1
print(d)
# {'Hello': 2, 'World': 1, 'Python': 2, 'Code': 1, 'Test': 1, 'with': 1}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;dict.get(key, default) : dictionary에 key값을 반환한다. key값이 없으면 default를 반환한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;[ 추가 문제 ]&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;각 단어별로 위치의 Index들을 저장하는 Dictionary를 반환하라. : dictionary ==&amp;gt; {word : [ index 1st , index 2th, ... ] } ex) {&quot;Hello&quot;: [0, 3] , &quot;Python&quot; : [2, 7] , ... }&lt;/p&gt;
&lt;pre id=&quot;code_1653368372946&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import defaultdict
input_val = [&quot;Hello&quot;, &quot;World&quot;, &quot;Python&quot;, &quot;Hello&quot;, &quot;Code&quot;, &quot;Test&quot;, &quot;with&quot;, &quot;Python&quot;]
d = defaultdict(list)
for i,w in enumerate(input_val):
  d[w].append(i)
print( d )
# {'Hello': [0, 3], 'World': [1], 'Python': [2, 7], 'Code': [4], 
#           'Test': [5], 'with': [6]})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;스택/큐 (Stack/Queue)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스택 (Push/Pop), LIFO/FIFO, 큐 (Queue)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;DeQueue&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372949&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import deque

dq=deque() # 덱 생성
dq.append() # 덱의 가장 오른쪽에 원소 삽입
dq.popleft() # 가장 왼쪽 원소 반환
dq.appendleft() # 덱의 가장 왼쪽에 원소 삽입
dp.pop() # 가장 오른쪽 원소 반환
dp.clear() # 모든 원소 제거
dp.copy() # 덱 복사
dp.count(x) #x와 같은 원소의 개수를 계산&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로그래머스 스택/큐 - 기능개발 문제 풀이&lt;/p&gt;
&lt;pre id=&quot;code_1653368372949&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(progresses, speeds):
    answer = []
    dq, s = [x for x in progresses], speeds
    
    while( len(dq)&amp;gt;0 ):
        r = 100-dq[0]
        div, remainder = r//s[0], r%s[0]
        nTimes = div if remainder==0 else div+1

        # update deploy of all functions
        dq = [x + nTimes*s[ti] for ti, x in enumerate(dq) ]

        # check if finish of each dev. and save the result into stack
        stack = []
        for ti,x in enumerate(dq):
            if x &amp;gt;= 100:
                stack.append(ti)
            else:
                break

        c = len(stack)
        answer.append( c )
        dq, s = dq[c:], s[c:]
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;힙 (Heap)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Heap은 이진트리 구조로써, 최소값 최대값을 쉽게 구하기 위하여 특정 조건이 적용된 트리이다.&lt;br /&gt;Heap 을 이용한 우선순위 큐&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;힙&lt;/b&gt;(&lt;span&gt;heap&lt;/span&gt;)은 최댓값 및 최솟값을 찾아내는 연산을 빠르게 하기 위해 고안된 완전이진트리(complete binary tree)를 기본으로 한 자료구조(tree-based structure)로서 다음과 같은 힙 속성(property)을 만족한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A가 B의 부모노드(parent node) 이면, A의 키(key)값과 B의 키값 사이에는 대소관계가 성립한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;220&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFPpbw/btrC178sWGw/TaKKTJckJNofy5mcqJ6VPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFPpbw/btrC178sWGw/TaKKTJckJNofy5mcqJ6VPk/img.png&quot; data-alt=&quot;힙의 구조. Heap. 출처 : 위키피디아&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFPpbw/btrC178sWGw/TaKKTJckJNofy5mcqJ6VPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFPpbw%2FbtrC178sWGw%2FTaKKTJckJNofy5mcqJ6VPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;220&quot; height=&quot;264&quot; data-origin-width=&quot;220&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;힙의 구조. Heap. 출처 : 위키피디아&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;heap 자주 사용하는 함수
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;heappush / heappop&lt;/li&gt;
&lt;li&gt;heapify() --&amp;gt; 기존 list를 heapq 구조체로 자체 변환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1653368372951&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import heapq as hq

h=[]
hq.heappush(h, 30)
hq.heappush(h, 10)
hq.heappush(h, 20)
hq.heappush(h, 15)

print(h) # [10, 15, 20, 30]
print(hq.heappop(h)) # 10
print(h) # [15, 30, 20]

h2 = [10, 1,2,3,9,5]
hq.heapify(h2)
print(h2)  # [1, 3, 2, 10, 9, 5]
print(h2[0]) # 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;Min Heap&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372952&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import heapq as hq
h = [4,1,2,3,9,5]
hq.heapify(h)
print(h)
min_heap = [hq.heappop(h) for _ in range(len(h))]
print(min_heap)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;Max Heap&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372952&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Max Heap --&amp;gt; 음수화
h2 = [4,1,2,3,9,5]
h2 = [ -1*x for x in h2]
hq.heapify(h2)
max_heap = [-1*hq.heappop(h2) for _ in range(len(h2))]
print(max_heap)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;Max Heap : tuple을 사용하는 경우&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372954&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import heapq as hq
heap_items = [1,3,5,7,9]
h=[]
for x in heap_items:
    hq.heappush(h, (-x,x))
print(h) # [(-9, 9), (-7, 7), (-3, 3), (-1, 1), (-5, 5)]
print([ x[1] for x in h])  # [9, 7, 3, 1, 5]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Heap을 사용한 예제 : 프로그래머스 &quot;더 맵게&quot;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참조 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42626&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/42626&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1653368372955&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import heapq

def solution(scoville, K):
    answer = 0
    heapq.heapify(scoville)
    
    for i in range(1000000000):
        if len(scoville)&amp;lt;=1: return -1
        heapq.heappush(scoville, heapq.heappop(scoville) + heapq.heappop(scoville)*2)
        answer+=1
        if scoville[0]&amp;gt;=K : 
            return answer

    return -1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;정렬 (Sort)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여러가지 기준으로 정렬, 문제를 풀어보자&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;단순정렬 (List) , 오름차순&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1653368372958&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;a = [1, 5, 2, 6, 3, 7, 4]
d = sorted(a)
print(d) # [1, 2, 3, 4, 5, 6, 7]&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;단순정렬 (List), 내림차순 (reverse=True)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1653368372958&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;a = [1, 5, 2, 6, 3, 7, 4]
d = sorted(a, reverse=True)
print(d) # [7, 6, 5, 4, 3, 2, 1]&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;내림차순 정렬을 할 때, 오름차순으로 정렬 후 전체 순서를 반대로 뒤집어서 처리할 수도 있다. `d = sorted(a)[::-1]`&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Sort by Key&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 정렬하고자 하는 Key를 별도로 지정할 때&lt;/h4&gt;
&lt;pre id=&quot;code_1653368372960&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;a = [1, 5, 2, 6, 3, 7, 4]
b = [10, 2, 5, 7, 3, 1, -1]
c = [ (x,y) for x,y in zip(a,b)]

e = sorted(c, key=lambda x: x[1])
print(e) # [(4, -1), (7, 1), (5, 2), (3, 3), (2, 5), (6, 7), (1, 10)]
print([ x[0] for x in e]) # [4, 7, 5, 3, 2, 6, 1]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Dictionary 관련 정렬&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1653368372963&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;a = {'a': 10, 'f': 5, 'c':3, 'b': 15, 'e': 20, 'd':13}

b = sorted(a)
c = sorted(a.items())
d = sorted(a.items(), key=lambda x: x[1])
print( b ) # ['a', 'b', 'c', 'd', 'e', 'f']
print( c ) # [('a', 10), ('b', 15), ('c', 3), ('d', 13), ('e', 20), ('f', 5)]
print( d ) # [('c', 3), ('f', 5), ('a', 10), ('d', 13), ('b', 15), ('e', 20)]&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;dictionary 자체만 사용하면 기본적으로 Key를 반환한다. `dict.items()` 는 &quot;Key-Value&quot; 쌍을 튜플로 반환해준다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt; 완전탐색 (Full Search)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1653368372964&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;시간만 충분하다면, 완전 탐색이 명확하지...&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;완전 탐색은 수많은 방법이 있기 때문에, for 문과 조건검색을 잘 사용하면 될것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Python의 경우는, List Compression, map, Lambda, zip 등이 유용하게 사용될 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또한, 만약 Numpy 등을 사용할 수 있다면, Python은 최고의 해결법이 될 것 이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다음은 프로그래머스 &quot;완전탐색&quot; 영역의 &quot;모의고사&quot;문제 이다.&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;lt; 문제 정의&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다음 패턴 3개를 주어진 배열(Array)와 Full Matching하여 Matching되는 갯수를 세는 문제이다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...&lt;/li&gt;
&lt;li&gt;2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...&lt;/li&gt;
&lt;li&gt;3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5,&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매칭된 갯수가 동일 (max치가 여러개)일 때 인덱스로 정렬하여 제출하는 것만 유의하면 크게 문제될것이 없다.&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1653368372965&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(answers):
    answer = []
    n = len(answers)
    s1 = [1, 2, 3, 4, 5] * (n//5+1)
    s2 = [2, 1, 2, 3, 2, 4, 2, 5] * (n//8+1)
    s3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5] * (n//10+1)
    s = [s1[:n], s2[:n], s3[:n] ]

    c = [0,0,0]
    for i,x in enumerate(answers):
        c = [ c[j]+1 if x-s[j][i]==0 else c[j] for j in range(3)]
    m = max(c)
    d = [x for x in zip(c, [1,2,3])]
    e = [x[1] for x in d if x[0]==m]

    return sorted(e)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;이분 탐색 (Binary Search)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1653368372966&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size23&quot; data-ke-style=&quot;style1&quot;&gt;완전탐색은 너무 오래걸려. 효율적으로 값을 찾아보자.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;깊이/너비 우선 탬색 (DFS/BFS)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1653368372967&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;탐색 방식 : 깊이 우선? 너비 우선?&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;( 작성중 )&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;탐욕 알고리즘 (Greedy Algorithm)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;로컬 최적이 전체 최적이 되는 경우&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;로컬에서 주어진 데이터에서 최적을 선택을 하고, 전체로 확대 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 때 주어진 list 등에서 추가(Insert)하거나, 제거 (remove)하면, 전체 List가 변하기 때문에, 반복문에 영향이 가지 않도록 유의 해야 한다. 대표적으로, 다음과 같은 명령어가 있다고 하면,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372967&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for x in y:
	if x&amp;gt;5: y.remove(x)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;for문이 y의 원소인데 중간에 y의 원소를 추가 삭제하면, Loop가 정상적으로 동작하지 않는다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 프로그래머스의 탐용법 (Greedy) 알고리즘의 체육복 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 정의는 다음 접은글을 확인 하기 바란다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체육복이 도난당함. 체육복을 보유한 학생만 수업에 참석 가능. 최대 수업참석 학생수를 구하는 문제&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;n : 전체 학생수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;lost : 체육복을 잃어버린 학생 인덱스&lt;span style=&quot;background-color: #fafafa;&quot;&gt;(array)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;caret-color: auto; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;reserve: 여벌의 체육복 보유 학생의 인덱스 (array)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;여벌의 체육복이 있는 학생들이 빌려줄 수 있음. 여벌의 체육복이 있는 학생 (reserve)는 자신의 앞번호/뒷번호만 빌려줄수 있음&lt;/li&gt;
&lt;li&gt;여벌의 체육복을 보유한 학생이, 또다른 한벌을 도난당했을 수도 있음. 이 경우 다른 사람에게 빌려줄 수 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1653368372968&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(n, lost, reserve):
    answer = 0
    lost.sort()
    reserve.sort()
    lost_self =[]
    rs = reserve.copy()
    for r in rs:
        if r in lost:
            lost.remove(r)
            reserve.remove(r)
    for r in reserve:
        if (r-1 in lost):
            lost.remove(r-1)
            continue
        elif (r+1 in lost): 
            lost.remove(r+1)
            continue
            
    return n-len(lost)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;동적 계획법/다이나믹 프로그래밍 (Dynamic Programming)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;반복되는 계산은 줄인다....&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동적 계획법이 활용될 수 있는 경우는, 수열로 표현이 되는 경우이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, `X(t) = X(t-1) + X(t-2)` 등과 같이 반복적으로 표현 되는 경우라 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분 Recursive 형태로 표현이 가능한 경우, 동적 계획법을 사용하면 효과적이라 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 동적 계획법은 동일한 연산이 반복 되기 때문에, 1) 이러한 연산을 미리 저장 (Memoization) 해 놓고 이를 참조해서 사용하는 방법, 2) 혹은 Recursion을 사용하는 방법으로 나뉜다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 프로그래머스의 동적계획법 (Dynamic Programming) 문제중, &quot;정수 삼각형&quot; 문제의 풀이이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 정의는 다음 접은글 확인&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;삼각형을 이루는 숫자가 주어진다.&lt;/li&gt;
&lt;li&gt;삼각형의 꼭대기에서 바닥까지 이어지는 경로중 거쳐간 숫자의 합이 가장 큰경우를 찾는 문제&lt;/li&gt;
&lt;li&gt;아래로 한칸씩만 이동할 수 있다. 즉, 바로 아래 왼/오른쪽 숫자 둘중 하나로만 이동이 가능하다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;아래와 같은 삼각형을 표현할 때 입력을 Array:&lt;br /&gt;&lt;span style=&quot;background-color: #202b3d; color: #b2c0cc;&quot;&gt;[[7], [3, 8], [8, 1, 0], [2, 7, 4, 4], [4, 5, 2, 6, 5]]&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc2NVQ/btrCZTiXJMy/JMNboTvSONXJnzln74fqb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc2NVQ/btrCZTiXJMy/JMNboTvSONXJnzln74fqb0/img.png&quot; data-alt=&quot;정삼각형의 꼭대기에서 바닥까지 이어지는 경로중 최대값 찾기 문제 (동적계획법)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc2NVQ/btrCZTiXJMy/JMNboTvSONXJnzln74fqb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc2NVQ%2FbtrCZTiXJMy%2FJMNboTvSONXJnzln74fqb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;186&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정삼각형의 꼭대기에서 바닥까지 이어지는 경로중 최대값 찾기 문제 (동적계획법)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 다음과 같은 식으로 표현이 가능하기 때문에 동적계획법을 사용하기에 최적 문제이다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;r행, c열 위치에서 최대값은, r+1행의 c열과, r+1행 c+1열의 값에 의존한다. 현 위치의 값인 triangle[r][c]는 고정된 상수이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;따라서, r행 c열에서의 최대값은 다음과 같이 정의할 수 있다.&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;t[r][c] = triangle[r][c] + max( t[r+1][c] , t[r+1][c+1] )&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;단, 초기 값은 설정을 해 주어야 한다.&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;t[ 마지막행] [ 각 열 ] = triangle[마지막행] [ 각 열]&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 위 내용을 코드로 표현하면 다음과 같이 표현 할 수 있다. 차이점이 있다면, 삼각형의 밑변부터 위로 올라오며 계산한 부분만 차이라 할 수 있겠다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653368372970&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(triangle):
    answer = 0
    t = [ [0]*len(x) for x in triangle ]
    nRows = len(triangle)
    
    for r in range(nRows)[::-1]:
        # print(f' - {r}th : {t}')
        for c in range(r+1):
            if r==nRows-1:
                t[r][c] = triangle[r][c]
            else:
                t[r][c] = triangle[r][c] + max(t[r+1][c], t[r+1][c+1])
    
    return t[0][0]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;box-sizing: border-box; border-right-width: 0px; border-top-width: 0px; border-left: #F15F5F 12px solid; border-bottom: #FFD8D8 2px solid; line-height: 1.7; margin-right: 0px; padding: 3px 5px 3px 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt; 그래프 이론 (Graph Theory)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1653368372971&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;노드(Node)와 엣지(Edge)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;( 작성중 )&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 이야기/Python</category>
      <category>Greedy</category>
      <category>Python Cheatsheet</category>
      <category>동적계획법</category>
      <category>자료구조</category>
      <category>정렬</category>
      <category>코딩테스트 컨닝페이퍼</category>
      <category>코딩테스트 핵심요약</category>
      <category>탐색</category>
      <category>탐욕법</category>
      <category>힙(Heap)</category>
      <author>리치윈드 - windFlex</author>
      <guid isPermaLink="true">https://windflex.tistory.com/187</guid>
      <comments>https://windflex.tistory.com/187#entry187comment</comments>
      <pubDate>Tue, 24 May 2022 14:02:10 +0900</pubDate>
    </item>
  </channel>
</rss>