<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3963934897749362059</id><updated>2024-12-08T03:12:44.285-08:00</updated><category term="python"/><category term="c++"/><category term="vc"/><category term="linux"/><category term="golang"/><category term="c"/><category term="docker"/><category term="git"/><category term="web"/><category term="github"/><category term="util"/><category term="android"/><category term="api"/><category term="html"/><category term="iphone"/><category term="javascript"/><category term="mac"/><category term="mssql"/><category term="mysql"/><category term="network"/><category term="plugin"/><category term="svn"/><category term="windows"/><category term="단축키"/><category term="도서"/><category term="C++11"/><category term="JSON"/><category term="PIL"/><category term="ajax"/><category term="aptana"/><category term="asp"/><category term="c. c++"/><category term="command"/><category term="error"/><category term="font"/><category term="format string"/><category term="gollum"/><category term="idle"/><category term="iis"/><category term="java"/><category term="jquery"/><category term="kivy"/><category term="library"/><category term="mysql 설치"/><category term="nforge"/><category term="node.js"/><category term="osx"/><category term="pip"/><category term="powershell"/><category term="python2.7"/><category term="sublime"/><category term="text"/><category term="리눅스"/><category term="수경재배"/><category term="엑셀"/><category term="영어"/><category term="자바스크립트"/><category term="정규식"/><category term="컵홀더"/><category term="&amp;&amp;"/><category term="++"/><category term="--"/><category term=".app"/><category term=".svn 폴더 삭제"/><category term="//"/><category term="1.#INFO0"/><category term="1.#IO"/><category term="1.#J"/><category term="1.$"/><category term="1st class citizens"/><category term="40가지 성공원리"/><category term="7z"/><category term="7zip"/><category term="7가지 자원"/><category term="Adplus"/><category term="AutoHotKey"/><category term="BBCode"/><category term="BSD license"/><category term="C2DM"/><category term="C4512"/><category term="Confluence"/><category term="CppCheck"/><category term="DebugFunInfo"/><category term="Designer"/><category term="GetTickCount()"/><category term="Google"/><category term="HideSlide.js"/><category term="Homebrew"/><category term="IIFE"/><category term="IOCP"/><category term="JIRA"/><category term="LVALUE"/><category term="Measuring execution time"/><category term="MyBATIS"/><category term="Native client"/><category term="OFFICE"/><category term="Obfuscator"/><category term="Overlapped IO"/><category term="PC에서 카카오톡"/><category term="PHMB"/><category term="PHMG"/><category term="Perforce"/><category term="Pillow"/><category term="PostgreSQL"/><category term="Programming"/><category term="PyCharm 설치"/><category term="Python IDLE"/><category term="RVALUE"/><category term="Rpository"/><category term="VC 디버깅"/><category term="VCi"/><category term="WinDbg"/><category term="Windows 10"/><category term="XMPP"/><category term="air server"/><category term="ajax control toolkit"/><category term="and"/><category term="aria"/><category term="asp study"/><category term="asp.net"/><category term="assembler"/><category term="atl"/><category term="baas"/><category term="bash 사용"/><category term="be going to"/><category term="beautifulsoap"/><category term="blogger"/><category term="bowpad"/><category term="browser"/><category term="c#"/><category term="canvas"/><category term="caret"/><category term="caret_extra_width"/><category term="carry"/><category term="cat.dto"/><category term="centos"/><category term="chart"/><category term="chatServer"/><category term="chrome"/><category term="cityfarmer"/><category term="close tab"/><category term="cmd"/><category term="code assist"/><category term="coding style"/><category term="coffee"/><category term="color syntax highlight"/><category term="concurrency"/><category term="const"/><category term="cookie"/><category term="cordova"/><category term="cpu stress test"/><category term="create-cat.dto"/><category term="css 셀렉터"/><category term="cup holder"/><category term="custom thema"/><category term="cximage"/><category term="datk render"/><category term="debug"/><category term="delete"/><category term="des"/><category term="divmod"/><category term="diy"/><category term="dll"/><category term="droid draw"/><category term="eclipse"/><category term="editor"/><category term="ee"/><category term="else"/><category term="emmet"/><category term="encrypt"/><category term="enumerate"/><category term="everything"/><category term="excel"/><category term="fiddler"/><category term="file search"/><category term="firewall"/><category term="flake8"/><category term="flask"/><category term="flow-chart"/><category term="font-size"/><category term="for"/><category term="for..each"/><category term="free library"/><category term="gcc"/><category term="get"/><category term="getFunName"/><category term="googletest"/><category term="grabber"/><category term="greenfish icon pro"/><category term="hangul"/><category term="hdd serial"/><category term="hdd 교체"/><category term="hole punching"/><category term="html 태그 제거"/><category term="html5"/><category term="http"/><category term="http packet monitor"/><category term="iBATIS"/><category term="icon"/><category term="iconfx"/><category term="iis7"/><category term="iis8"/><category term="inline"/><category term="ios"/><category term="ios sample source"/><category term="ipad"/><category term="iperf"/><category term="isAdmin()"/><category term="jdk"/><category term="jenkins"/><category term="jinja2"/><category term="jsUnit"/><category term="json viewer"/><category term="jsp"/><category term="korean character"/><category term="l4"/><category term="l7"/><category term="link"/><category term="linux firewall"/><category term="list"/><category term="local"/><category term="localaccount"/><category term="macro"/><category term="mantis"/><category term="maria db"/><category term="markdown"/><category term="mathmatica"/><category term="maven"/><category term="md5"/><category term="message"/><category term="mfc"/><category term="minikube"/><category term="minus shift"/><category term="mobile os"/><category term="mobile web"/><category term="msdev"/><category term="msdev 2008"/><category term="mssql DB 마이그레이션"/><category term="mssql error"/><category term="mssql 설치"/><category term="msvc"/><category term="nano"/><category term="networking"/><category term="nginx"/><category term="no hostkeys"/><category term="notepad++"/><category term="ns-chart"/><category term="odbc"/><category term="odbc32"/><category term="open"/><category term="optimization"/><category term="or"/><category term="p2p"/><category term="package install"/><category term="pdf 프린터"/><category term="phonegap"/><category term="picture control"/><category term="pitaya"/><category term="plantuml"/><category term="plyer"/><category term="post"/><category term="predicatie"/><category term="predis"/><category term="protobuf"/><category term="proxy"/><category term="proxy server"/><category term="puml"/><category term="put"/><category term="pycharm"/><category term="pycon 2016"/><category term="pydoc"/><category term="python thinker gui designer PAGE"/><category term="python2"/><category term="python3"/><category term="python3.5"/><category term="radis"/><category term="rar"/><category term="reflection"/><category term="resiprocate"/><category term="rest"/><category term="restlet"/><category term="review"/><category term="run console"/><category term="rvalue referance"/><category term="rvalue reference"/><category term="seed"/><category term="server"/><category term="sha"/><category term="shall"/><category term="shared"/><category term="shift"/><category term="side-by-side"/><category term="simulator"/><category term="singleton"/><category term="singletone"/><category term="size specification"/><category term="snippets"/><category term="sns"/><category term="soap"/><category term="socket"/><category term="source"/><category term="sourcetree"/><category term="sphinx"/><category term="spint3 restfull"/><category term="ssh-server"/><category term="ssl"/><category term="std::copy"/><category term="std::sort()"/><category term="std::unary_function"/><category term="stress"/><category term="svn merge"/><category term="switch"/><category term="syntex"/><category term="template"/><category term="template class"/><category term="terninal"/><category term="test"/><category term="thread"/><category term="time"/><category term="timeGetTime()"/><category term="tinyxml"/><category term="tizen"/><category term="tomcat"/><category term="tomcat 설치"/><category term="tools"/><category term="transparent"/><category term="triplet"/><category term="ubuntu"/><category term="update-cat.dto"/><category term="utc"/><category term="utf-8"/><category term="utf8"/><category term="v.3.5.0"/><category term="var swap"/><category term="vbs"/><category term="vc++"/><category term="vcpkg"/><category term="virtualenv"/><category term="vpn"/><category term="vs2005"/><category term="vs2010"/><category term="walking the callstack"/><category term="web update"/><category term="webrtc"/><category term="websocket"/><category term="werkzeug"/><category term="will"/><category term="wireshark"/><category term="wpf"/><category term="wsl2"/><category term="wtl"/><category term="xaml"/><category term="xmlns"/><category term="zen coding"/><category term="zk"/><category term="zlib license"/><category term="가르마"/><category term="가습기 살균제"/><category term="강좌"/><category term="개념"/><category term="거치대"/><category term="고어텍스"/><category term="공감각"/><category term="공기순환"/><category term="공부잘하는법"/><category term="교육"/><category term="글로벌K"/><category term="기억"/><category term="난독화 툴"/><category term="난로"/><category term="논리식"/><category term="눈운동"/><category term="대동천자문"/><category term="데자르뎅 운동"/><category term="도시농부"/><category term="돋보기"/><category term="디버깅"/><category term="로켓 화로 캠핑"/><category term="로프"/><category term="롯지"/><category term="리눅스 개발 환경"/><category term="마크다운"/><category term="마크업언어"/><category term="매듭"/><category term="매크로"/><category term="맥"/><category term="맥북프로"/><category term="맷돌"/><category term="멀티플라이어"/><category term="메모리 교체"/><category term="면적 변환"/><category term="모바일 웹 페이지"/><category term="무설치"/><category term="무쇠솥"/><category term="배움의 기술"/><category term="벡터 그래픽툴"/><category term="보안 점검"/><category term="블루씨드"/><category term="비비코드"/><category term="사용자 환경 설정"/><category term="사회적 기업"/><category term="삼성"/><category term="생각의 탄생"/><category term="서버"/><category term="서버관리및 접속 툴"/><category term="서큘레이터"/><category term="석세스 플랜"/><category term="설정"/><category term="설치 오류"/><category term="세큘레이터"/><category term="소프트 쉘"/><category term="소학"/><category term="소학언해"/><category term="수경재배기"/><category term="수액"/><category term="숫자"/><category term="숫자글"/><category term="쉘"/><category term="쉘러"/><category term="스칼렛"/><category term="스타일"/><category term="스타트업"/><category term="스토브"/><category term="스펀지"/><category term="시각주의력"/><category term="시뮬레이터"/><category term="시제"/><category term="신용협동 조합"/><category term="아몰레드"/><category term="아이듄즈 서버"/><category term="아이패드"/><category term="아이폰"/><category term="아이폰 동영상 변환"/><category term="안드로이드 어플 개발"/><category term="암호화"/><category term="압축"/><category term="압축제외목록"/><category term="애플 TV"/><category term="약어"/><category term="에디터"/><category term="에스프레소"/><category term="연관 기억법"/><category term="연산자"/><category term="연산자 우선순위"/><category term="영 단어"/><category term="영어 약어"/><category term="오피스"/><category term="온라인"/><category term="우선순위"/><category term="웹"/><category term="위키마크업"/><category term="위키텍스트"/><category term="윈도우"/><category term="윈도우10"/><category term="윈도우7"/><category term="윈도우즈용 아이콘 파일 편집기"/><category term="이클립스"/><category term="이클립스 설치"/><category term="이클립스 활용"/><category term="인식"/><category term="인터프리터 창"/><category term="잉크스케이프"/><category term="전용면적"/><category term="정규표현식"/><category term="제거"/><category term="주민 등록 발급기 위치 안내."/><category term="주소창"/><category term="주의점"/><category term="직관"/><category term="직접실행"/><category term="찾기/바꾸기"/><category term="천자문"/><category term="카드"/><category term="카카오 API"/><category term="캠핑"/><category term="커피"/><category term="커피 종류"/><category term="코넬식 학습장 정리"/><category term="코드 압축기"/><category term="코딩"/><category term="탐색기"/><category term="테스트"/><category term="토리즈"/><category term="토빈세(tobin tax)"/><category term="툴스"/><category term="파워쉘"/><category term="파이썬"/><category term="페치카"/><category term="평형"/><category term="포맷터"/><category term="포터블"/><category term="푸시서버"/><category term="프로젝트 만들기"/><category term="플랫폼"/><category term="플러그인"/><category term="학습장 정리"/><category term="학습학"/><category term="한글"/><category term="한글깨짐"/><category term="함수"/><category term="화로"/><category term="화면 갱신 대기"/><category term="히스토리"/><title type='text'>더 나은 미래를 향하여.</title><subtitle type='html'>alexnetster@gmail.com/&#xa;나중에 재사용시 흔적을 남겨 찾기 쉽게 하는 것이 목적/&#xa;최대한 간단하게.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>246</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-5137212313270951792</id><published>2024-04-11T19:50:00.000-07:00</published><updated>2024-04-11T19:50:29.419-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><category scheme="http://www.blogger.com/atom/ns#" term="pitaya"/><category scheme="http://www.blogger.com/atom/ns#" term="protobuf"/><title type='text'>golang .protobuf go_package 오류 나는 문제.</title><content type='html'>&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-sider-select-id=&quot;6365915c-6050-437b-8fae-c171fc0fce87&quot;&gt;1.golang용 protocol buffer 관련 모듈은 다운로드 받았음&lt;/p&gt;&lt;p data-sider-select-id=&quot;6365915c-6050-437b-8fae-c171fc0fce87&quot;&gt;go get -d -u google.golang.org/protobuf&lt;/p&gt;&lt;p&gt;go install github.com/golang/protobuf/protoc-gen-go&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. pitaya 샘플 .proto 파일 생성을 시도 했으나, 아래 오류가 발생하면서 빌드 실패함&lt;/p&gt;&lt;p data-sider-select-id=&quot;6365915c-6050-437b-8fae-c171fc0fce87&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-sider-select-id=&quot;09a1f053-7d97-4102-96a0-d1d0f49c0a68&quot;&gt;&lt;span data-sider-select-id=&quot;ab073ecb-8d32-477c-bfb8-056e9d074d23&quot; style=&quot;background-color: #ffa400;&quot;&gt;D:\pitaya&amp;gt;protoc --proto_path=examples\demo\worker\protos --go_out=plugins=grpc:. examples\demo\worker\protos\*.proto&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;protoc-gen-go: unable to determine Go import path for &quot;arg.proto&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;Please specify either:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; • a &quot;go_package&quot; option in the .proto source file, or&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; • a &quot;M&quot; argument on the command line.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;--go_out: protoc-gen-go: Plugin failed with status code 1.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;D:\pitaya&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-sider-select-id=&quot;6365915c-6050-437b-8fae-c171fc0fce87&quot;&gt;stackoverflow 등 참고해도 비슷하지만 다른 내용들 뿐.&lt;/p&gt;&lt;div&gt;.proto 파일내에 option go_package = &quot;../protos_gen&quot;; 내용 추가하여 빌드하니 잘됨.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p data-sider-select-id=&quot;774c7f61-8908-48c3-86f1-c6ba1697c92f&quot;&gt;3.기존 소스&lt;/p&gt;&lt;p&gt;--------------------------------&lt;/p&gt;&lt;p data-sider-select-id=&quot;efce7ee3-2f6a-4106-bab1-23cee09779e9&quot;&gt;&lt;span data-sider-select-id=&quot;11f5d717-a4a2-4426-adbe-81c5cc57f20d&quot; style=&quot;background-color: #ffa400;&quot;&gt;syntax = &quot;proto3&quot;;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;package protos;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;message Arg {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&amp;nbsp; string msg = 1;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;}&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p data-sider-select-id=&quot;774c7f61-8908-48c3-86f1-c6ba1697c92f&quot;&gt;4.신규 소스&lt;/p&gt;&lt;p&gt;--------------------------------&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;div data-sider-select-id=&quot;c0cec185-8343-4b33-bc5e-6943dfbecc86&quot;&gt;&lt;span data-sider-select-id=&quot;61770d3d-6f76-4ece-a673-4ff3ff8fca93&quot; style=&quot;background-color: #ffa400;&quot;&gt;syntax = &quot;proto3&quot;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;package protos;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div data-sider-select-id=&quot;c3d5191e-3666-40ad-8225-21fc1aa56444&quot;&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;option go_package = &quot;../protos_gen&quot;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;message Arg {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;&amp;nbsp; string msg = 1;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: #ffa400;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;__endic_crx__&quot;&gt;&lt;div class=&quot;css-diqpy0&quot;&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/5137212313270951792/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2024/04/golang-protobuf-gopackage.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/5137212313270951792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/5137212313270951792'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2024/04/golang-protobuf-gopackage.html' title='golang .protobuf go_package 오류 나는 문제.'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-142588333507301455</id><published>2024-03-28T21:46:00.000-07:00</published><updated>2024-03-28T21:49:42.005-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="concurrency"/><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><title type='text'>Concurrency in Go 책 읽고 대략 요약</title><content type='html'>&lt;p&gt;원본은&amp;nbsp;https://laced-river-472.notion.site/Concurrency-in-Go-7f97812aee104adc8cc6d60591f01316 에 요약 해놓음.&lt;/p&gt;&lt;p&gt;2024년 3월 27일 ~ 2024년 3월 29일&lt;/p&gt;
&lt;p&gt;Concurrency in go 책 검토&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/SK-Jin/concurrency-in-go-src&quot;&gt;https://github.com/SK-Jin/concurrency-in-go-src&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;1장 동시성 소개&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;동시성이 어려운 이유&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2장 코드 모델링: 순차적 프로세스간의 통신(CSP)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;동시성과 병렬성의 차이&lt;/li&gt;
&lt;li&gt;동시성을 지원하는 언어의 장점&lt;/li&gt;
&lt;li&gt;Go의 동시성의 철학&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3장 동시성 구성요소&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;goroutine&lt;/li&gt;
&lt;li&gt;Sync Package&lt;/li&gt;
&lt;li&gt;Channels&lt;/li&gt;
&lt;li&gt;select-statement&lt;/li&gt;
&lt;li&gt;defer-statment&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4장 동시성 패턴&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;제한(Confinement)
&lt;ol&gt;
&lt;li&gt;Ad-hoc
&lt;ol&gt;
&lt;li&gt;내부적인 규칙, 암묵적인 규칙 등 시간적인 문제로 깨트려지는 경우가 있을 수 있음.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;lexical
&lt;ol&gt;
&lt;li&gt;도구에서 문제 상황에 대해 통보, 이를 개선 하는 형태로 접근&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;동기화를 사용할 수 있다면, 제한을 추구해야 함.
&lt;ol&gt;
&lt;li&gt;성능을 향상시키고, 개발자의 인지 부하를 줄이기 위함&lt;/li&gt;
&lt;li&gt;동기화에는 비용이 들며, 이를 피할 수 있으면, 임계 염역이 없기 때문에 동기화 비용을 지불할 필요가 없음.&lt;/li&gt;
&lt;li&gt;동기화로 인해 발생 가능한 모든 문제도 막을 수 있음&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;for-select 루프
&lt;ol&gt;
&lt;li&gt;채널에서 반복 변수 보내기&lt;/li&gt;
&lt;li&gt;멈추기를 기다리면서 무한히 대기&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;고루틴 누수 방지
&lt;ol&gt;
&lt;li&gt;고루틴 작지만 리소스를 필요로 함.&lt;/li&gt;
&lt;li&gt;가비지 콜렉터에 의해 수집 되지 않음. -&amp;gt; 원인은 제각각 이겠지만, 여전히 활성화 되어 있을 것이므로&lt;/li&gt;
&lt;li&gt;고루틴 종료 조건
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;작업 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;복구할 수 없는 에러로 인해 더 이상 작업을 계속할 수 없을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;작업을 중단하라는 요청을 받았을 떄 -&amp;gt; 네트워크 효과(연관된 고루틴 존제)가 있으므로 제일 중요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;접근 1
&lt;ol&gt;
&lt;li&gt;Cancel chan 생성 하여 기존 for~range 구조에셔 for~select 구조 변경 cancel 요청 감시 하도록 수정&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;접근 2
&lt;ol&gt;
&lt;li&gt;Cancel chan 생성, 기존 for 구조에서 for~select 구조 변경 cancel 요청 감시 하도록 수정&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;or-channel
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;때로는 하나 이상의 done 채널을 하나의 done 채널로 결합해, 그 중 하나의 채널이 닫힐때 결합된 채널이 닫히도록 해야할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;select 로 처리하면 좋으나, 때때로 런타임 작업 중인 done 채널 갯수를 알지 못하는 경우가 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;재귀 및 고루틴들을 통해 복합done 채널 생성&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;에러처리
&lt;ol&gt;
&lt;li&gt;error path 에 주의?&lt;/li&gt;
&lt;li&gt;에러 처리의 책임자는 누구인가?
&lt;ol&gt;
&lt;li&gt;호출한 함수에게 오류 상황을 반환하여 알린다.
&lt;ol&gt;
&lt;li&gt;type Result struct { // &amp;lt;1&amp;gt;
Error    error
Response *http.Response
}
checkStatus := func(done &amp;lt;-chan interface{}, urls ...string) &amp;lt;-chan Result { // &amp;lt;2&amp;gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;파이프라인
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;긴 하나의 함수? 대신에 파이프라인 처리가 향후 관리에서도 효율적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;어떤 시스템을 변경하고, 하나의 논리적인 변화를 위해 여러 영역을 변경하였다면, 잘못된 추상화 가능성 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;시스템에서 추상화를 구성하는 데 사용할 수 있는 또 다른 도구&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;특히, 프로그램이 스트림이나 데이터에 대한 일괄 처리 작업들을 처리해야 할 때 매우 강력한 도구&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;파이프라인의 각각의 단계를 스테이지(Stage) 라고 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;하나의 단계를 데이터를 가져와서 변환을 수행하고, 데이터를 다시 전송하는 것.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;파이프 라인 중  팬 인, 팬 아웃 가능, 속도를 제한 하는 것도 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;함수형 프로그램 과 연관, 모나드 가 생각 날 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;단계를 수정하지 않고, 높은 수준에 수정으로 원하는 바를 얻을 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;pipeline []int 입력, multiply, add 형태로 구현, 출력이 chan int 형태가 되도록 generator, multiply, Add 구현 하여 호출&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;기존 예제와 차이점&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&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;li&gt;기존 함수형 호출은 모든 단계가 완료되어야 처음부터 입력이 가능하지만, 파이프라인은 출력이 비워지는 순간 입력이 채워지게 되므로 사실상 여러 단계가 동시에 동작하는 효과가 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;파이프라인 생성기&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;이산 값의 집합을 채널의 값 스트림으로 변환하는 함수
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;유용한 생성기들&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;repeat 주어진 값들을 순차적으로 반복&lt;/li&gt;
&lt;li&gt;함수에서 주어진 값들을 반복&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Pan-out, Pan-in
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;파이프라인의 특정 단계에서 시간이 많이 걸리는 경우, 다른 단계에 영향을 미침.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;파이프라인의 흥미로운 점, 개별 단계를 조합해 데이터 스트림에서 연산 할 수 있고, 파이프라인을 여러번 재사용 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;여러개의 고루틴을 통해, 파이프라인의 상류 단계로 부터 데이터를 가져오는 것을 병렬화하면서 파이프라인 한단계를 재사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;팬 아웃 : 파이프라인의 입력을 처리하기 위해 여러 개의 고루틴 들로 시작하는 프로세스&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;팬 인 : 여러 결과를 하나의 채널로 결합하는 프로세스&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 여러 소비자가 읽어 들이는 하나의 다중화된 채널을 생성하는 것,&lt;/li&gt;
&lt;li&gt;= 하나의 입력 채널마다 고루틴을 동작 시키는 것&lt;/li&gt;
&lt;li&gt;= 입력 채널이 모두 닫혔을때 다중화된 채널을 닫는 하나의 고루틴과 관련돼 있음.&lt;/li&gt;
&lt;li&gt;= 결과가 도착하는 순서가 중요하지 않은 경우 사용.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;팬인, 팬아웃 적용 가능한 곳&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 단계가 이전에 계산한 값에 의존하지 않는다. 즉 순서 독립성을 가진다.&lt;/li&gt;
&lt;li&gt;= 단계를 실행하는데 시간이 오래 걸린다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;8.or-done 채널
&lt;ol&gt;
&lt;li&gt;Or 채널에 Done 채널 처리가 추가된 형태, Done  입력시 연관 채널 종료 처리&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;9.tee 채널
&lt;ol&gt;
&lt;li&gt;입력 하나에 대해 2개의 출력을 처리 하는 채널,&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;10.bridge 채널
&lt;ol&gt;
&lt;li&gt;genval 에서 채널집합(채널당 값 이 들어간 채널)을 하나씩 넣고 닫는다.&lt;/li&gt;
&lt;li&gt;bridge 패턴에서는 각각 전달 받은 채널을 받아서 하나의 입력으로 처리해 준다.
&lt;ol&gt;
&lt;li&gt;chanStream &amp;lt;-chan &amp;lt;-chan interface{},
intChanStream := make(chan (&amp;lt;-chan interface{})) // &amp;lt;2&amp;gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;대기열 사용(queuing)
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;파이프라인이 아직 준비 되지 않았더라도, 파이프라인에 작업을 받아들이는 것이 유용할 때가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;대기열을 널리 사용하지 않는 이유.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 프로그램 최적화 마지막 단계에 적용함.&lt;/li&gt;
&lt;li&gt;= 대기열을 성급하게 도입하면 데드락이나 라이브락 과 같은 동기화 문제가 드라나지 않을 수 있음&lt;/li&gt;
&lt;li&gt;= 프로그램이 정확해짐에 따라 대기열이 얼마나 필요한지 알게 될 수 있음.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;대기열이 프로그램의 총 실행 속도를 높여주지는 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 단지, 프로그램이 다른 방식으로 동작하도록 도와줌.&lt;/li&gt;
&lt;li&gt;= 대신에 좀 더 CPU 유휴시간을 활용할 수 있게 도와줌.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;대기열 사용이 시스템의 전반적인 성능을 향상시킬 수 있는 상황.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 특정 단계에서 일괄 처리 요청이 시간을 절약하는 경우&lt;/li&gt;
&lt;li&gt;= 특정 단계의 지연으로 인해 시스템에 피드백 루프가 생성되는 경우&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;파일 쓰기시 정킹 단위로 한번에 수행 처리, IO 처리 속도 개선 효과&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;상위단계의 지연이 파이프라인 전체에 영향을 미침,&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 보통 상위단계에서 단계별로 영향을 발생, 파악이 어려울수 있음.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;파이프 라인의 효율성이 특정 임꼐 값 아래로 떨어지면 파이프 라인 상류 단계의 시스템이&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 파이프라인으로의 입력을 늘리기 시작하고, 파이프라인 효율의 저하로 이어짐... 죽음의 나선 시작&lt;/li&gt;
&lt;li&gt;= 실패에 대한 안전장치(fail-safe) 가 없으면 파이프라인을 이용하는 시스템은 결코 회복 되지 않음.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;시간 초과 처리는 필수, 죽은 요청 처리하다가 피드백 루프를 생성해 파이프 라인의 효율을 떨어뜨림.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;대기열의 상황은 몇몇 상황에서만 파이프라인의 실행시간을 단축시킴.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;여기저기 파이프라인 도입시 오히려 늦어질 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;리틀의법칙(little&#39;s law) : 대기열 사용 이론에서 충분한 샘플링을 통한 파이프라인의 처리량을 예측하는 법칙&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 진입 속도와 탈출 속도가 같은 경우에만 도입해야 함.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Context 패키지
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;고루틴 취소를 위한 Done 처리는 잘 동작하지만, 단순하면서 제한 적이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;취소되었다는 알림 대신, 취소 이유가 무엇인지, 또는 함수가 마감 시한이 있는지 추가적인 정보가 있다면 도움이 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;시스템 크기에 상관없이 일반적으로 이들 정보를 Done 채널로 감쌀 필요가 있다는 것이 확실함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;그래서, Done 을 표준 패턴화 하고 패키지 한 것이 context 패키지.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;두가지 주요 목적&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 호출 그래프상의 분기를 취소하기 위한 AIP 제공&lt;/li&gt;
&lt;li&gt;= 호츨 그래프를 따라 요청 범위request-scope 데이터를 전송하기 위한 데이터 저장소(data-bag) 제공&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;함수의 취소 한다는 것의 의미 -&amp;gt; context 패키지에서 관리 가능함.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 고루틴의 부모가 해당 고루틴을 취소하고자 할 수 있다.&lt;/li&gt;
&lt;li&gt;= 고루틴이 자신의 자식을 취소하고자 할 수 있다.&lt;/li&gt;
&lt;li&gt;= 고루틴 내의 모든 대기 중인 작업은 취소 될 수 있도록 선점 가능할 필요가 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;Context 에 타입을 다르게 선언하면 값은 같아도 추가 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;type foo int
type bar int
func main() {
		m := make(map[interface{}]int)
		m[foo(1)] = 1
		m[bar(1)] = 2

		fmt.Printf(&quot;%v&quot;, m)	//map[1:2 1:1]
}

//- Context 의 인스턴스에 값을 저장해야 함.
type ctxKey int

const (
	ctxUserID ctxKey = iota
	ctxAuthToken
)

func UserID(c context.Context) string {
	return c.Value(ctxUserID).(string)
}

func AuthToken(c context.Context) string {
	return c.Value(ctxAuthToken).(string)
}

func ProcessRequest(userID, authToken string) {
	ctx := context.WithValue(context.Background(), ctxUserID, userID)
	ctx = context.WithValue(ctx, ctxAuthToken, authToken)
	HandleResponse(ctx)
}

&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;5장 확장에서의 동시성&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;에러전파&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;분산 등의 처리 쉽게 오류가 발생할 수 있음. 하지만 문제의 원인을 파악하기 쉽지 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;크고 복잡한 시스템에서 오류를 어떻게 전달해야 할까?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;오류 처리를 자신의 것으로 하는 방안이 필요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;에러에서 취해야 하는 정보&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 발생한 사전
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;디스크가 찼다,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;소켓이 닫혔다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;자격이 만료되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;= 발생한 장소 와 시점
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;호출이 시작된 메서드 부터, 에러가 발생한 위치가 있는 전체 스택 트레이스 포함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;실행중인 콘텍스트 관련 정보 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;분산 시스템인 경우에는 발생한 시스템 정보 표시 해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;에러 시간은 UTC 기준 시간으로 표시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;= 사용자 친화적인 메세지
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;시스템 및 시스템의 사용자에 맞춰 조정해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;친화적인 메세지는 인간 중심적이며 문제가 일시적인지 여부를 포함해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;= 사용자가 추가적인 정보를 얻는 방법
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;어떤 시점에 누군가는 에러가 발생했을때 일어난 일을 자세히 알고 싶어 할 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;사용자에게 표시되는 에러는 에러가 기록된 시간이 아닌 발생한 시간.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;에러가 생성 됐을때의 전체 스택 트레이스 등 에러의 전체 정보를 표시하는 로그에 상호 참조할수 있는 방법(또는 ID) 제공 해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;버그 추적 시스템에서 비슷한 문제를 집계하는 데 도움이 되는 스택 트레이스의 해시 값을 포함하는 방식도 유용.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;= 아무런 정보 없이 오류만 노출 되는 것은 실수 이며 버그.
에러에 대해 생각할 수 있는 범용적인 프레임워크 필요.
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;모든 에러는 2가지로 나뉨.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;++ 버그 - 사용자가 시스템에 맞춰 정의하지 않은 에러 또는 &quot;처리되지 않은&quot; 에러&lt;/li&gt;
&lt;li&gt;++ 알려진 예외적인 경우(네트워크 단전, 디스크 쓰기 실패)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;모든 오류를 다 감싸서 호출한 곳으로 전달할 필요는 없음.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;++ 자기 모듈 혹은 코드에 유용한 콘텍스트를 추가할 수 있는 경우에만 에러를 감싸서 전달.&lt;/li&gt;
&lt;li&gt;++ 나저지는 처리 하지 않음. 처음 발생한 곳에서 이미 오류 처리를 하고 있을 것이므로&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2.시간 초과 및 취소&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;동시성 코드로 작업할 떄, 시간 초과(timeout) 이나 취소(cancellation)가 자주 발생함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;시간 초과는 동작을 이해할 수 잇는 시스템을 만드는 여러 요소 가운데 결정적인 요소&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;취소는 시간 초과에 따르는 자연스러운 반응.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;동시 프로세스가 시간 초과를 지원하기를 원하는 이유&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 시스템 포화
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;시스템 경계에 잇는 요청이 오랜 시간 후에 처리되는 것 보다는 시간 초과 되는 것을 원할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;++ 시간 촉화 되었다고 해도 요청이 반복될 가능서잉 낮음&lt;/li&gt;
&lt;li&gt;++ 메모리 내 요청을 저장하기 위한 메모리, 영속적인 대기열을 저장하기 위한 디스크 공간등 요청을 저장할 수 있는 리소스가 부족함.&lt;/li&gt;
&lt;li&gt;++ 시간이 지날수록 요청 또는 전송 중인 데이터의 필요성이 줄어듬.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;= 오래된 데이터
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;어떤 데이터는 적절한 데이터가 있을 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;데이터가 만료되기 전에 처리 해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;context.WithDeadline, context.WithTimeout, context.Cancel 등을 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;= 데드락을 막으려는 시도
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;모든 동시 작업에 시간 초과를 설정하는 것은 불합리 하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;시간 초과 기간을 설정하는 목적은 데드락을 막기 위한 것, 적당한 사간 내에 차단 해제될 만큼만 짧으면 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;데드락을 파하기 위해 시간 초과를 설정하려는 시도는 잠재적으로 시스템에서 데드락을 유발하는 문제를 라이브락을 유발하는 문제로 바꿀 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;++ 대형 시스템은 구성품이 훨씬 많으므로 재부팅을 통한 시스템 복구를 통한 데드락 보단, 시간이 허락되면 복구가 가능한 라이브락이 나음.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;동시 프로세스가 취소 되는 이유&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 시간 초과 - 암묵적인 취소&lt;/li&gt;
&lt;li&gt;= 사용자 개입&lt;/li&gt;
&lt;li&gt;= 부모 프로세스의 취소&lt;/li&gt;
&lt;li&gt;= 복제된 요청 - 여러곳에 동시 요청 빠른 응답 온곳 빼고 나머지는 취소..&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3.하트비트&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;2가지 유형의 하트비트(HeartBit)&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 일정 시간 간격으로 발생하는 하트비트&lt;/li&gt;
&lt;li&gt;= 작업 단위 시작 부분에서 발생하는 하트비트&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;데드락 또는 무한 또한 장시간 대기 같은 장애 시에 짧은 시간내에 원인 파악 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4.복제된 요청&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;일부 어픞리케이션의 경우, 가능한 빨리 응답을 받는 것이 최우선 과제.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;성능상의 이점을 위해 일종의 교환을 할수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 여러 핸들러에게 요청을 복제할수 있고, 그중 하나는 다른 핸들러보다 빠르게 리턴 될 것.&lt;/li&gt;
&lt;li&gt;= 리소스를 소모를 해서 여러개를 돌리는 단점이 있으나, 빨리 응답 온것중 하나를 답하고, 나머지는 취소&lt;/li&gt;
&lt;li&gt;= 응답 속도가 비슷한 경우 리소스 소모하여 요청하는 것이 의미 없으므로 적용하면 안됨.&lt;/li&gt;
&lt;li&gt;= 설치, 유지보수 등의 비용이 비싸지만, 속도가 목적인 경우 사용.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;5.속도 제한&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;속도 제한이란?&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 리소스에 대한 접근을 단위 시간당 특정 횟수로 제한 하는 것.&lt;/li&gt;
&lt;li&gt;= 여기서 리소스는 API 연결, 디스크 읽기/쓰기, 네트워크 패킷, 에러 등&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;속도 제한을 적용하는 이유&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&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;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;분산 시스템에서 합법적인 사용자가 너무 많은 양의 작업을 수행하거나,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;버그가 있는 코드를 수행하므로 인해 다른 사용자의 시스템 성능을 저하시킬수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;증상&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;= 분산 데이터베이스에서 쿠럼(Quorum:완료되었다고 여겨지는 작업에 반드시 응답해야 하느 서버의 수)을 잃어 버리고, 쓰기를 허용하지 않게 돼, 기존 요청이 실패하게 되며, 결국 뭔가 잘못된 일이 일어날 수 있음을 알 수 있음.&lt;/li&gt;
&lt;li&gt;= 결국 시스템이 스스로에게 Ddos 같은 공격을 수행하게 됨.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;Go 에서 속도 제한 알고리즘&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;= 토큰버켓(Token Bucket)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;리소스를 이용하려면, 접근 토콘이 있어야 하며,  접근 토큰이 없는 경우, 사용이 제한된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;토큰의 깊이는 d 이며, 한번에 d 개까지 토큰은 사용가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;토큰이 사용가능할 때까지 대기열에서 기다리던가, 요청을 거부 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;참고 코드&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;import &quot;[golang.org/x/time/rate](&amp;lt;http://golang.org/x/time/rate&amp;gt;)&quot;
func Open() *APIConnection {
	return &amp;amp;APIConnection{
		apiLimit: MultiLimiter(
			rate.NewLimiter(Per(2, time.Second), 2),
			rate.NewLimiter(Per(10, time.Minute), 10),
		),
		diskLimit: MultiLimiter(
			rate.NewLimiter(rate.Limit(1), 1),
		),
		networkLimit: MultiLimiter(
			rate.NewLimiter(Per(3, time.Second), 3),
		),
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;참고 코드2&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-go&quot;&gt;type APIConnection struct {
	networkLimit,
	diskLimit,
	apiLimit RateLimiter
}
func (a *APIConnection) ReadFile(ctx context.Context) error {
	if err := MultiLimiter(a.apiLimit, a.diskLimit).Wait(ctx); err != nil {
		return err
	}
	// Pretend we do work here
	return nil
}

func (a *APIConnection) ResolveAddress(ctx context.Context) error {
	if err := MultiLimiter(a.apiLimit, a.networkLimit).Wait(ctx); err != nil {
		return err
	}
	// Pretend we do work here
	return nil
}

&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;6.비정상 고루틴의 치료&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;데몬과 같이 수명이 긴 프로세스에서는 수명이 긴 고루틴의 집합을 사용하는 것이 일반적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;요점은 고루틴이 외부의 도움없이 복구 할수 없는 나쁜 상태에 빠지기 쉽다는 점.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;장시간 사용하는 고루틴이 건강한 상태인지 확인하고, 건강한 상태가 아니면, 재시작하도록 하는 것이 도움이 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;고루틴을 관리하는 스튜어트(steward: 관리인)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;모니터링 되는 고루틴을 와드(ward: 피후견인)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;스튜어트는 와드의 고루틴이 비정상적인 상태가 되면 해당 고루틴을 재시작하도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;이를 위해 해당 고류틴을 재시작할 수 함수의 참조가 필요함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;6장 고루틴과 Go 런타임&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;!--notionvc: 67163f07-82e3-4d2a-a15f-3e4b04b6f3f6--&gt;&lt;div id=&quot;__endic_crx__&quot;&gt;&lt;div class=&quot;css-diqpy0&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id=&quot;__endic_crx__&quot;&gt;&lt;div class=&quot;css-diqpy0&quot;&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/142588333507301455/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2024/03/concurrency-in-go.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/142588333507301455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/142588333507301455'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2024/03/concurrency-in-go.html' title='Concurrency in Go 책 읽고 대략 요약'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-876734195848234827</id><published>2024-03-21T23:16:00.000-07:00</published><updated>2024-03-22T00:21:00.870-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><category scheme="http://www.blogger.com/atom/ns#" term="plantuml"/><category scheme="http://www.blogger.com/atom/ns#" term="puml"/><title type='text'>golang 소스에서 ClassDiagram UML 파일 생성</title><content type='html'>&lt;p&gt;1. 전체적인 진행 목표는 아래와 같다.&lt;/p&gt;&lt;p&gt;golang source 분석&amp;nbsp;&lt;/p&gt;&lt;p&gt;-&amp;gt; .puml 파일 생성&amp;nbsp;&lt;/p&gt;&lt;p&gt;-&amp;gt; 파일 내용을 plantuml.com (또는 local plautuml 서버) 에서 이미지 확인&lt;/p&gt;&lt;p&gt;-&amp;gt; 분석용 또는 문서화 용으로 사용.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. 먼저 plautuml 웹 서비스 환경을 준비한다. plantuml 은 다양한 Uml 타입을 지원하는데, 텍스트를 입력하면 해당 내용을 UML 이미지로 생성해준다.&lt;/p&gt;&lt;p&gt;2.1. 기존 platuml 웹서비스 주소 접속 아래 도커 설치는 필요하지 않음. https://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000&lt;/p&gt;&lt;p&gt;2.2. 또는 로컬에 docker 설치하여 http://localhost:8080/ 접속하기 위한 방법 은 다음 방법 참고&lt;/p&gt;&lt;p&gt;2.2.1. https://plantuml.com/ko/starting 에 가면 docker 에 설치하는 방법 있슴.&lt;/p&gt;&lt;p&gt;2.2.2 .도커가 이미 설치된 상태에서 콘솔창에서 다음을 입력함&lt;/p&gt;&lt;p&gt;docker run -d -p 8080:8080 plantuml/plantuml-server:jetty&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;3.&amp;nbsp; golang 용 폴더 생성 (참고링크: https://github.com/jfeliu007/goplantuml )&lt;/p&gt;&lt;p&gt;go mod init&amp;nbsp;&lt;/p&gt;&lt;p&gt;go get github.com\jfeliu007\goplantuml\parser&lt;/p&gt;&lt;p&gt;go install github.com\jfeliu007\goplantuml\cmd\goplantuml@latest&lt;/p&gt;&lt;p&gt;goplantuml folder &amp;gt; folder.puml&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;4. 생성된 .puml 을 편집기에서 해당 내용을 읽어 plantuml.com 에 접속하여 편집기 화면에 붙여 넣기를 수행하면 우측 또는 하단에 해당 내용을 이용하여 Uml(여기서는 ClassDiagram) 이미지가 생성 됨.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;5. 아래 링크는 java 파일을 이용하여 .puml을 png 형식으로 파일을 생성하는 방법도 있습니다.&lt;/p&gt;&lt;p&gt;https://sonumb.tistory.com/101&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이상입니다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div id=&quot;__endic_crx__&quot;&gt;&lt;div class=&quot;css-diqpy0&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id=&quot;__endic_crx__&quot;&gt;&lt;div class=&quot;css-diqpy0&quot;&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/876734195848234827/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2024/03/golang-classdiagram-uml.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/876734195848234827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/876734195848234827'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2024/03/golang-classdiagram-uml.html' title='golang 소스에서 ClassDiagram UML 파일 생성'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-601721329132210059</id><published>2023-11-29T22:01:00.000-08:00</published><updated>2023-11-29T22:01:17.137-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cat.dto"/><category scheme="http://www.blogger.com/atom/ns#" term="create-cat.dto"/><category scheme="http://www.blogger.com/atom/ns#" term="github"/><category scheme="http://www.blogger.com/atom/ns#" term="update-cat.dto"/><title type='text'>netjs sample 불완전한 상태? 어디에서 다운로드 받을 수 있나?</title><content type='html'>&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1.회사에서 소스 분석할 일이 생겨서 확인중인데, nestjs 를 사용함.&lt;/p&gt;&lt;p&gt;2.nestjs 구조를 알아야 할 것만 같아서 가이드 를 찾아다니며 소스를 입력해서 돌아다니고 있었음.&lt;/p&gt;&lt;p&gt;3.nestjs sample 소스가 불 완전한 상태로 돌아다님. 전체 샘플 소스 없이 샘플 설명하는 경우가 있음. 이로인해 샘플 입력하고 동작 확인 불가함. 특히, 아래 소스가 없는 경우가 많음.&lt;/p&gt;&lt;p&gt;create-cat.dto.ts, update-cat.dto.ts&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;4.무엇이든 다 있는 git hub 에 이것과 관련한 소스가 올라와 있음. 참고하시길...&lt;/p&gt;&lt;p&gt;https://github.com/jmcdo29/testing-nestjs - 전체 소스&lt;/p&gt;&lt;p&gt;https://github.com/jmcdo29/testing-nestjs/tree/main/apps/http-sample - 이게 cats controller 를 인용한 소스 샘플&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/601721329132210059/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/11/netjs-sample.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/601721329132210059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/601721329132210059'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/11/netjs-sample.html' title='netjs sample 불완전한 상태? 어디에서 다운로드 받을 수 있나?'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-6198425882876704453</id><published>2023-08-21T00:38:00.006-07:00</published><updated>2023-08-21T00:55:05.548-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><category scheme="http://www.blogger.com/atom/ns#" term="minikube"/><category scheme="http://www.blogger.com/atom/ns#" term="powershell"/><title type='text'>[minikube] kubunetics 를 클라우드가 아닌 local 로 돌려보기 위한 도구</title><content type='html'>&lt;p&gt;https://minikube.sigs.k8s.io/docs/start/&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;조건.윈도우 docker desktop 최신 버전이 설치 되어 있어야 함.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;윈도우 PowerShell 에서 아래 동작으로 설치&lt;/p&gt;&lt;p&gt;winget install minikube&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;윈도우 cmd 쉘에서 다음 수행&lt;/div&gt;&lt;div&gt;C:\Program Files\Kubernetes\Minikube&amp;gt; minikube start&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;이후 docker에서 콘테이너 minikube 실행되고 있는 것을 확인할 수 있음.&lt;/div&gt;&lt;div&gt;그러나, kubenetic 내 image, container 는 별도로 동작함.&amp;nbsp;&lt;/div&gt;&lt;div&gt;아래 명령으로 설치된 container 확인 가능&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;kubectl get services&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/6198425882876704453/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/08/minikube-kubunetics-local.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/6198425882876704453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/6198425882876704453'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/08/minikube-kubunetics-local.html' title='[minikube] kubunetics 를 클라우드가 아닌 local 로 돌려보기 위한 도구'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-1285664727363491632</id><published>2023-08-04T01:46:00.007-07:00</published><updated>2023-08-04T01:46:52.156-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DebugFunInfo"/><category scheme="http://www.blogger.com/atom/ns#" term="getFunName"/><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><title type='text'>[golang] getFunName</title><content type='html'>&lt;p&gt;&amp;nbsp;import (&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;fmt&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;log&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;runtime&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// Debug prints a debug information to the log with file and line.&lt;/p&gt;&lt;p&gt;func DebugFunInfo(format string, a ...interface{}) {&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;funName := &quot;&quot;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;pc, file, line, ok := runtime.Caller(1)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;info := fmt.Sprintf(format, a...)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;// https://stackoverflow.com/questions/35212985/is-it-possible-get-information-about-caller-function-in-golang&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;details := runtime.FuncForPC(pc)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;if ok &amp;amp;&amp;amp; details != nil {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;funName = details.Name()&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;//fmt.Printf(&quot;called from %s\n&quot;, details.Name())&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;log.Println(&quot;debug&quot;, funName, &quot;file:&quot;, file, &quot;(&quot;, line, &quot;) &quot;, info)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;func main() {&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&lt;/span&gt;DebugFunInfo&lt;span style=&quot;white-space: normal;&quot;&gt;(&quot;start&quot;)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/1285664727363491632/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/08/golang-getfunname.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/1285664727363491632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/1285664727363491632'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/08/golang-getfunname.html' title='[golang] getFunName'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-8171345730405734078</id><published>2023-08-02T03:25:00.001-07:00</published><updated>2023-08-02T03:25:39.551-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatServer"/><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><category scheme="http://www.blogger.com/atom/ns#" term="nano"/><title type='text'>[golang] gameframework nano ChatServer</title><content type='html'>&lt;p&gt;&amp;nbsp;golang&amp;nbsp; nano 채팅서버 + WebClient&lt;/p&gt;&lt;p&gt;https://github.com/lonng/nano/tree/master/examples/cluster&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;start cluster master&lt;/p&gt;&lt;p&gt;start cluster chat --listen &quot;127.0.0.1:34580&quot;&lt;/p&gt;&lt;p&gt;start cluster gate --listen &quot;127.0.0.1:34570&quot; --gate-address &quot;127.0.0.1:34590&quot;&lt;/p&gt;&lt;p&gt;rem start explorer microsoft-edge:http://127.0.0.1:12345/web/&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/8171345730405734078/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/08/golang-gameframework-nano-chatserver.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/8171345730405734078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/8171345730405734078'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/08/golang-gameframework-nano-chatserver.html' title='[golang] gameframework nano ChatServer'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-6002523046375448806</id><published>2023-07-31T19:18:00.011-07:00</published><updated>2023-08-01T02:10:32.307-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="websocket"/><title type='text'>[golang/websocket] websocket sample</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;0.소스 올린 이유.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;div&gt;샘플이라고 올라와 있지만, 실제로는&amp;nbsp; 접속 실패 오류가 떠서 한참 구글링 했습니다.&lt;/div&gt;&lt;div&gt;server1.go 실행하고 client1.go 로 동작 확인하고, 웹 동작은 크롬 브라우저에서 websocket_client1.html 동작 확인 했습니다.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;아래는 WebSocket 동작 샘플 소스 이며,&lt;/div&gt;&lt;div&gt;아래 링크에 있는 샘플들을 참고 했습니다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;https://github.com/gorilla/websocket&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;https://github.com/gorilla/websocket/tree/main/examples/chat&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;https://stackoverflow.com/questions/4361173/http-headers-in-websockets-client-api&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;https://www.golinuxcloud.com/golang-websocket/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;https://www.tutorialspoint.com/webrtc/webrtc_rtcpeerconnection_apis.htm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;u&gt;server1.go&lt;/u&gt;&lt;/h3&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;package main&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;import (&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;fmt&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;log&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;net/http&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;github.com/gorilla/websocket&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// var upgrader = websocket.Upgrader{}&lt;/p&gt;&lt;p&gt;var upgrader = websocket.Upgrader{&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;ReadBufferSize:&amp;nbsp; 1024,&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;WriteBufferSize: 1024,&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; // 아래 CheckOrigin 항목이 없으면, 크롬에서 클라이언트 올렸을때 접속 안됨.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;CheckOrigin: func(r *http.Request) bool {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return true&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; },&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;func main() {&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;http.HandleFunc(&quot;/echo&quot;, func(w http.ResponseWriter, r *http.Request) {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;conn, err := upgrader.Upgrade(w, r, nil) // error ignored for sake of simplicity&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;if err != nil {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;log.Println(&quot;upgrade:&quot;, err)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;log.Println(&quot;w:&quot;, w)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;log.Println(&quot;r:&quot;, r)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;return&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;for {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;// Read message from browser&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;msgType, msg, err := conn.ReadMessage()&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;if err != nil {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;log.Println(&quot;read:&quot;, err)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;return&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;// Print the message to the console&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;fmt.Printf(&quot;%s sent: %s\n&quot;, conn.RemoteAddr(), string(msg))&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;// Write message back to browser&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;if err = conn.WriteMessage(msgType, msg); err != nil {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;log.Println(&quot;write:&quot;, err)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;return&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;})&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;http.HandleFunc(&quot;/&quot;, func(w http.ResponseWriter, r *http.Request) {&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;fmt.Fprintf(w, &quot;This is GolinuxCloud&#39;s websocket server&quot;)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;})&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;sPort := &quot;:9090&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;log.Println(&quot;server port &quot;, sPort)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;http.ListenAndServe(sPort, nil)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;u&gt;websocket_client1.html&lt;/u&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;html&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;head&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;lt;title&amp;gt;ws&amp;lt;/title&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;lt;script src=&quot;https://code.jquery.com/jquery-3.3.1.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;/head&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;body&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;!-- websockets.html --&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;input id=&quot;input&quot; type=&quot;text&quot; /&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;button onclick=&quot;send()&quot;&amp;gt;Send&amp;lt;/button&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;pre id=&quot;output&quot;&amp;gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;/body&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;script&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; var input = document.getElementById(&quot;input&quot;);&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; var output = document.getElementById(&quot;output&quot;);&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; var socket = new WebSocket(&quot;ws://localhost:9090/echo&quot;);&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; //var socket = new WebSocket(&quot;ws://10.120.10.102:9090/echo&quot;);&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; socket.onopen = function () {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; output.innerHTML += &quot;Status: Connected\n&quot;;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; };&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; socket.onmessage = function (e) {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; output.innerHTML += &quot;Server: &quot; + e.data + &quot;\n&quot;;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; };&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; function send() {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; socket.send(input.value);&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; input.value = &quot;&quot;;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; }&lt;/div&gt;&lt;div&gt;&amp;lt;/script&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;lt;/html&amp;gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;u&gt;client1.go&lt;/u&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;// #go run client1.go localhost:9090 echo&lt;/div&gt;&lt;div&gt;package main&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;import (&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;bufio&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;fmt&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;log&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;net/url&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;os&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;os/signal&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;time&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&quot;github.com/gorilla/websocket&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;var SERVER = &quot;&quot;&lt;/div&gt;&lt;div&gt;var PATH = &quot;&quot;&lt;/div&gt;&lt;div&gt;var TIMESWAIT = 0&lt;/div&gt;&lt;div&gt;var TIMESWAITMAX = 5&lt;/div&gt;&lt;div&gt;var in = bufio.NewReader(os.Stdin)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;func getInput(input chan string) {&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;result, err := in.ReadString(&#39;\n&#39;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;if err != nil {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;log.Println(err)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;input &amp;lt;- result&lt;/span&gt;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;func main() {&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;arguments := os.Args&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;if len(arguments) != 3 {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;fmt.Println(&quot;Need SERVER + PATH!&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;SERVER = arguments[1]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;PATH = arguments[2]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;fmt.Println(&quot;Connecting to:&quot;, SERVER, &quot;at&quot;, PATH)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;interrupt := make(chan os.Signal, 1)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;signal.Notify(interrupt, os.Interrupt)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;input := make(chan string, 1)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;go getInput(input)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;URL := url.URL{Scheme: &quot;ws&quot;, Host: SERVER, Path: PATH}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;c, _, err := websocket.DefaultDialer.Dial(URL.String(), nil)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;if err != nil {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;log.Println(&quot;Error:&quot;, err)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;defer c.Close()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;done := make(chan struct{})&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;go func() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;defer close(done)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;for {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;_, message, err := c.ReadMessage()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;if err != nil {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;log.Println(&quot;ReadMessage() error:&quot;, err)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;log.Printf(&quot;Received: %s&quot;, message)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;}()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;for {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;select {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;case &amp;lt;-time.After(4 * time.Second):&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;log.Println(&quot;Please give me input!&quot;, TIMESWAIT)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;TIMESWAIT++&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;if TIMESWAIT &amp;gt; TIMESWAITMAX {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;//syscall.Kill(syscall.Getpid(), syscall.SIGINT)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;case &amp;lt;-done:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;case t := &amp;lt;-input:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;err := c.WriteMessage(websocket.TextMessage, []byte(t))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;if err != nil {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;log.Println(&quot;Write error:&quot;, err)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;TIMESWAIT = 0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;go getInput(input)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;case &amp;lt;-interrupt:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;log.Println(&quot;Caught interrupt signal - quitting!&quot;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, &quot;&quot;))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;if err != nil {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;log.Println(&quot;Write close error:&quot;, err)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;				&lt;/span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;select {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;case &amp;lt;-done:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;case &amp;lt;-time.After(2 * time.Second):&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/6002523046375448806/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/07/golangwebsocket-websocket-sample.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/6002523046375448806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/6002523046375448806'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/07/golangwebsocket-websocket-sample.html' title='[golang/websocket] websocket sample'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-3947158218591986900</id><published>2023-03-30T02:59:00.003-07:00</published><updated>2023-03-30T02:59:47.959-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><title type='text'>[Docker] Docker 사용법</title><content type='html'>&lt;p&gt;&amp;nbsp;https://sddev.tistory.com/124&lt;/p&gt;&lt;p&gt;위 링크 내용을 가져와서 내용 습득을 위해 다시 한번 정리한 것입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 사용법&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;# Docker 개요&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;개발 환경 구성에 대한 문서를 계속 업데이트한다면 이런 문제가 최소화되겠지만,&amp;nbsp;&lt;/p&gt;&lt;p&gt;상상하는 것만으로도 진이 빠지는 일인 건 분명&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker 적용하기&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. local에서 프로젝트 폴더를 생성하고자 하는 경로에서, git clone해오거나, usb에서 프로젝트 폴더를 복사&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. 프로젝트 루트 디렉토리에서 도커 이미지 빌드 및 생성&lt;/p&gt;&lt;p&gt;[cmd] cd 프로젝트폴더경로&amp;nbsp;&lt;/p&gt;&lt;p&gt;[cmd] docker build -t (도커_이미지_이름)&lt;/p&gt;&lt;p&gt;(ex) docker build -t sdweb-docker-img&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// sdweb-docker-img라는 도커 이미지가 생성됨&lt;/p&gt;&lt;p&gt;// 아래의 명령어로 생성된 docker 조회 가능&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[cmd] docker image ls | grep (검색어)&lt;/p&gt;&lt;p&gt;(ex) docker image ls | grep sdweb-docker-img&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;3. 프로젝트 앱 컨테이너 실행 (2번의 이미지를 컨테이너로 실행)&lt;/p&gt;&lt;p&gt;[cmd] docker run -it --rm -p 8000:8000 sdweb-docker-img ./실행파일..?&lt;/p&gt;&lt;p&gt;// 데이터 베이스가 연결되어 있지 않기 때문에 에러남&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;4. 데이터베이스 컨테이너 실행&lt;/p&gt;&lt;p&gt;[cmd] docker run -it --rm (db도커이미지명)&lt;/p&gt;&lt;p&gt;(ex) docker run -it --rm protgres&lt;/p&gt;&lt;p&gt;// 기본적으로 도커 컨테이너들은 각각 격리된 환경에서 실행&lt;/p&gt;&lt;p&gt;// 다시 말해, 별도의 옵션을 지정하지 않으면 다른 컨테이너의 존재를 알 수 없음. 각각 실행만 시키면 무의미&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;5. 데이터베이스 컨테이너 연결&lt;/p&gt;&lt;p&gt;- 데이터베이스 컨테이너를 실행하면서 컨테이너 이름을 붙이고(db라고 하죠),&lt;/p&gt;&lt;p&gt;- 앱 컨테이너를 실행할 때 db 컨테이너를 연결해 줍니다.&lt;/p&gt;&lt;p&gt;docker run --rm(-it 노테이션 삭제함으로써 데몬 형태로 컨테이너 실행)\&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --name db(db 컨테이너 이름 붙임) \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_DB=djangosample(-e 노테이션으로 컨테이너 내 환경변수설정) \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_USER=sampleuser \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_PASSWORD=samplesecret \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; postgres(db도커이미지명)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;실행 명령&lt;/p&gt;&lt;p&gt;docker run --rm --name db -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser -e POSTGRES_PASSWORD=samplesecret postgres&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// 도커 허브의 공식 포스트그레SQL 저장소에 가보면 설정할 수 있는 환경 변수 종류가 존재&lt;/p&gt;&lt;p&gt;// 여기서 설정한 사용자 이름이나 비밀번호, 데이터베이스 이름 같은 환경변수들은&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;sdweb프로젝트폴더/settings.ts 파일 안에 설정해 둔 기본값들이다.&lt;/p&gt;&lt;p&gt;(프로젝트가 알고 있는 값)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;6. 앱 컨테이너 실행 및 데이터베이스 컨테이너 연결(link)&lt;/p&gt;&lt;p&gt;docker run -it --rm \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -p 8000:8000(앞의 8000은 도커를 설치한 호스트의 8000포트를, 컨테이너의 8000번 포트에 연결한다) \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --link db(db 컨테이너 이름 붙였던 것,--link: 참조할 다른 컨테이너를 지정) \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e DJANGO_DB_HOST=db \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e DJANGO_DEBUG=True \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; sdweb-docker-img \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ./manage.py runserver 0:8000(마지막 줄은 프로젝트 속성에 따라 실행 명령어 달라질 듯)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;실행 명령&lt;/p&gt;&lt;p&gt;docker run -it --rm -p 8000:8000 --link db -e DJANGO_DB_HOST=db -e DJANGO_DEBUG=True sdweb-docker-img ./manage.py runserver 0:8000&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// 연동도 완료되지만, 소스코드를 변경해도, 결과가 반영이 안되는 문제가 존재&lt;/p&gt;&lt;p&gt;// 프로젝트 폴더에 생성된 Dockerfile을 분석해 보면 10행의 ADD ./sdweb /app/sdweb/ 이라는 명령어를 통해&amp;nbsp;&lt;/p&gt;&lt;p&gt;// 컨테이너 밖의 소스를 컨테이너 안에 추가함으로써, 격리되어 더이상 소스코드 변경에 영향 받지 않음&lt;/p&gt;&lt;p&gt;// 수정할 소스 코드의 디렉터리를 앱 컨테이너 내부의 소스 코드와 연결하여,&amp;nbsp;&lt;/p&gt;&lt;p&gt;// 코드를 바꿀 때마다 컨테이너 속 코드도 바뀌게 하는 작업이 필요&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;7. 코드 변경이 실시간으로 반영되게 하기&lt;/p&gt;&lt;p&gt;// 기존 앱컨테이너 종료(Ctrl + C)&lt;/p&gt;&lt;p&gt;docker run -it --rm \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -p 8000:8000 \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --link db \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e DJANGO_DB_HOST=db \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e DJANGO_DEBUG=True \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --volume=$(pwd):/app/(--volume: 이 옵션을 사용하여 로컬 디렉터리의 특정 경로를 컨테이너 내부로 마운트, ($(pwd)는 이 명령을 실행하는 현재 디렉터리의 절대 경로, app폴더는 로컬디렉토리에서 격리된 컨테이너로 마운트할 수 있게 된다.) \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; sdweb-docker-img \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ./manage.py runserver 0:8000&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;8. 컨테이너 종료하기&lt;/p&gt;&lt;p&gt;// 앱 컨테이너 종료(Ctrl + C)&lt;/p&gt;&lt;p&gt;// 데이터베이스 컨테이너 종료&lt;/p&gt;&lt;p&gt;[cmd] docker stop db(기존에 지정했던 이름)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;9. 데이터베이스 데이터 보존&lt;/p&gt;&lt;p&gt;// 컨테이너 실행시 --rm 옵션을 지정할 경우, 데이터베이스 컨테이너가 종료와 함꼐 사라짐&lt;/p&gt;&lt;p&gt;// 그와 동시에 컨테이너 내부에 쌓였던 데이터베이스 데이터들도 모두 삭제(깔끔하지만, 개발용 데이터 매번 쌓기 귀찮)&lt;/p&gt;&lt;p&gt;// 데이터베이스가 데이터를 저장할 때 파일 시스템을 사용한다는 점을 생각해보면, 이를 해결할 때도 역시 --volume 옵션을 사용&lt;/p&gt;&lt;p&gt;$ mkdir -p ./docker/data //프로젝트 경로 내에서 &#39;docker/data&#39;라는 폴더 생성(이름 임의 지정 가능)&lt;/p&gt;&lt;p&gt;$ docker run -it --rm \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --name db \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_DB=djangosample \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_USER=sampleuser \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_PASSWORD=samplesecret \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --volume=$(pwd)/docker/data:/var/lib/postgresql/data \&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// 가운데 &#39;:&#39; 기호를 유의&lt;/p&gt;&lt;p&gt;// 데이터베이스 컨테이너 내부의 디렉터리(/var/lib/postgresql/data)를&amp;nbsp;&lt;/p&gt;&lt;p&gt;// 로컬 컴퓨터의 디렉터리($(pwd)/docker/data)로 연결&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; postgres:&lt;/p&gt;&lt;p&gt;// 이제 데이터베이스가 데이터를 저장할 파일 시스템으로 로컬 컴퓨터의&amp;nbsp; $(pwd)/docker/data 폴더를 사용&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 정리(순서 유의)&lt;/p&gt;&lt;p&gt;1. 데이터베이스 컨테이너 실행&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker run -it --rm \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --name db \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_DB=djangosample \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_USER=sampleuser \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e POSTGRES_PASSWORD=samplesecret \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --volume=$(pwd)/docker/data:/var/lib/postgresql/data \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; postgres&lt;/p&gt;&lt;p&gt;실행&lt;/p&gt;&lt;p&gt;docker run -it --rm --name db -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser e POSTGRES_PASSWORD=samplesecret --volume=$(pwd)/docker/data:/var/lib/postgresql/data postgres&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. 새 터미널 창에서 앱 컨테이너 실행&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker run -it --rm \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -p 8000:8000 \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --link db \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e DJANGO_DB_HOST=db \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; -e DJANGO_DEBUG=True \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; --volume=$(pwd):/app/ \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; django-sample \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ./manage.py runserver 0:8000&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// 위의 두개 명령어만으로도, DB와 잘 연결되고, 소스코드 변경하면 개발서버가 알아서 재시작&lt;/p&gt;&lt;p&gt;// 컨테이너를 종료해도 DB가 로컬에 저장&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker-compose로 개발 환경 구성하기&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;컨테이너 실행에 필요한 옵션을 docker-compose.yml이라는 파일에 적어두고, 컨테이너 간 실행 순서와 의존성을 관리하자!&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. docker-compose.yml 파일 만들기&lt;/p&gt;&lt;p&gt;- 장황한 도커 실행 옵션을 미리 적어둔 문서&lt;/p&gt;&lt;p&gt;- 프로젝트 루트에 파일을 만든다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;version: &#39;3&#39; // 파일 규격(규격에 따라 지원하는 옵션 달라짐, 3으로 시작하는 최신버전 사용)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;services:&amp;nbsp; &amp;nbsp; // 해당 항목 밑에 실행하려는 컨테이너 정의(containers == services)&lt;/p&gt;&lt;p&gt;&amp;nbsp; db:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // postgres docker이미지 서비스의 이름을 db로 지정하였음&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; image: postgres // 해당 서비스(db라는 컨테이너)가 사용할 도커이미지명&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // postgres 명칭은&amp;nbsp; dockerhub의 공식 postgres 이미지&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; volumes:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // 컨테이너 내부 폴더와 로컬 폴더 사이의 마운트 관계 지정(격리를 푸는 연결 통로)&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - ./docker/data:/var/lib/postgresql/data // &#39;./&#39;은 로컬의 루트프로젝트 폴더경로&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // 컨테이너 내 var/lib/portgresql/data를 로컬 내 projectRoot/docker/data로 마운트&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; environment:&amp;nbsp; &amp;nbsp; // 컨테이너 내부의 환경변수 지정(docker run 명령어의 -e 옵션과 대응)&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - POSTGRES_DB=sampledb&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - POSTGRES_USER=sampleuser&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - POSTGRES_PASSWORD=samplesecret&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - POSTGRES_INITDB_ARGS=--encoding=UTF-8 // 데이터베이스 서버의 인코딩 설정&lt;/p&gt;&lt;p&gt;&amp;nbsp; sdweb:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // 앱 서비스의 이름을 sdweb으로 지정&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; build:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // db 컨테이너 서비스와 다르게 앱은 특정 이미지(redis, postgres...) 대신 build 옵션을 추가&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; context: .&amp;nbsp; &amp;nbsp; // docker build 명령을 실행할 디렉토리 경로&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; dockerfile: ./compose/django/Dockerfile-dev //&amp;lt;개발용&amp;gt; 도커이미지를 빌드하는데 사용할 Dockerfile 지정&lt;/p&gt;&lt;p&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; //개발용 Dockerfile-dev에서는 소스코드를 앱 컨테이너에 넣지 않음(로컬 소스가 실시간 반영이 안되므로)&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; environment:&amp;nbsp; &amp;nbsp; // 앱 서비스의 환경 변수로 지정(DB 접속정보는 db 서비스에 입력한 것과 동일해야함)&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - DJANGO_DEBUG=True&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // 각 값들을 프로젝트 소스 내의 설정관련된 부분에서 불러와 사용&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - DJANGO_DB_HOST=db&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - DJANGO_DB_PORT=5432&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - DJANGO_DB_NAME=sampledb&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - DJANGO_DB_USERNAME=sampleuser&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - DJANGO_DB_PASSWORD=samplesecret&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - DJANGO_SECRET_KEY=dev_secret_key&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ports:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // docker run 명령어의 -p 옵션에 해당하는 부분(포트 지정)&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - &quot;8000:8000&quot;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; command:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // 앱 컨테이너를 실행시 가장 마지막에 적었던 명령어 부분&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - python manage.py runserver 0:8000&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; volumes:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // docker run 명령어의 -volumes 옵션에 해당하는 부분(마운트 지정)&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - ./:/app/&amp;nbsp; &amp;nbsp; // 컨테이너 내 app 폴더를 로컬 내 루트 프로젝트 폴더로 마운트&lt;/p&gt;&lt;p&gt;^z&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# docker-compose 명령어 실행&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[yml파일이 있는루트 프로젝트 폴더경로] docker-compose up -d&lt;/p&gt;&lt;p&gt;// http://127.0.0.1:8000에 접속해보면 개발 서버가 잘 작동함을 확인 가능&lt;/p&gt;&lt;p&gt;// up -d : yml 파일 내용에 따라 이미지를 BUILD하고, 서비스(컨테이너)를 실행합니다.&lt;/p&gt;&lt;p&gt;// -d: 서비스 실행 후 콘솔로 빠져나옵니다.&lt;/p&gt;&lt;p&gt;// --force-recreate: 컨테이너를 지우고 새로 만듭니다.&lt;/p&gt;&lt;p&gt;// --build: 서비스(컨테이너) 시작 전 이미지를 새로 만듭니다.&lt;/p&gt;&lt;p&gt;(dock run 명령어로 자동생성되는 운영환경설정기록인 Dockfile로 build하여 동일한 이미지를 만든다.)&lt;/p&gt;&lt;p&gt;(이미지를 통해 격리된 컨테이너를 생성한다.)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. 서비스를 띄울 네트워크 설정&lt;/p&gt;&lt;p&gt;2. 필요한 볼륨 생성(혹은 이미 존재하는 볼륨과 연결)&lt;/p&gt;&lt;p&gt;3. 필요한 이미지 풀(pull)&lt;/p&gt;&lt;p&gt;4. 필요한 이미지 빌드(build)&lt;/p&gt;&lt;p&gt;5. 서비스 의존성에 따라 서비스 실행&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[루트 프로젝트 폴더경로] docker-compose ps : 현재 환경에서 실행중인 각 서비스의 상태 조회&lt;/p&gt;&lt;p&gt;[루트 프로젝트 폴더경로] docker-compose stop : 현재 환경에서 실행중인 서비스를 멈춥니다.&lt;/p&gt;&lt;p&gt;[루트 프로젝트 폴더경로] docker-compose start : 현재 환경에서 실행중인 서비스를 시작합니다.&lt;/p&gt;&lt;p&gt;[루트 프로젝트 폴더경로] docker-compose down --volume: 현재 환경에서 컨테이너, 네트워크 삭제, 또는 볼륨까지도 삭제&lt;/p&gt;&lt;p&gt;[루트 프로젝트 폴더경로] docker-compose exec (명령어) : 실행 중인 컨테이너에서 명령어 실행&lt;/p&gt;&lt;p&gt;[루트 프로젝트 폴더경로] docker-compose logs (서비스,컨테이너명) : 서비스명 없으면 모든 서비스의 로그&lt;/p&gt;&lt;p&gt;-f: 지금까지 쌓인 로그를 다 보여준 후에도 셸로 빠져나오지 않고, 로그가 쌓일 때마다 계속해서 출력합니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 단축명령어 적용하기(맥 또는 리눅스)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;~/.bashrc나 ~/.zshrc 파일 상에 alias 적용&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;alias dco=&#39;docker-compose&#39;&lt;/p&gt;&lt;p&gt;alias dcb=&#39;docker-compose build&#39;&lt;/p&gt;&lt;p&gt;alias dce=&#39;docker-compose exec&#39;&lt;/p&gt;&lt;p&gt;alias dcps=&#39;docker-compose ps&#39;&lt;/p&gt;&lt;p&gt;alias dcr=&#39;docker-compose run&#39;&lt;/p&gt;&lt;p&gt;alias dcup=&#39;docker-compose up&#39;&lt;/p&gt;&lt;p&gt;alias dcdn=&#39;docker-compose down&#39;&lt;/p&gt;&lt;p&gt;alias dcl=&#39;docker-compose logs&#39;&lt;/p&gt;&lt;p&gt;alias dclf=&#39;docker-compose logs -f&#39;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# docker-compose 버전 차이&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;- 2 : links 항목을 통해 연결할 컨테이너 지정해주어야 했음&lt;/p&gt;&lt;p&gt;- 3 : 동일 네트워크 안에 있는 서비스끼리 서로 통신 가능&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# tip&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. docker-compose.yml 수정 후, 서비스들에 적용하길 원하는 경우&lt;/p&gt;&lt;p&gt;docker-compose.yml 파일을 수정하고 이를 서비스에 적용하려면 서비스를 멈추고(stop), 서비스를 지우고(rm),&amp;nbsp;&lt;/p&gt;&lt;p&gt;서비스를 시작해야(up) 합니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;하지만 up 명령만 실행해도, (현재 실행 중인 서비스 설정과 달라진 부분이 있다면) 알아서 컨테이너를 재생성하고&amp;nbsp;&lt;/p&gt;&lt;p&gt;서비스를 재시작해줍니다.*&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. Dockerfile-dev 파일 수정 후, 서비스들에 적용하길 원하는 경우&lt;/p&gt;&lt;p&gt;up 명령에 다음과 같이 --build 옵션을 넣으면 알아서 이미지를 새로 만들고 서비스를 재시작합니다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker-compose up -d --build [서비스_이름]&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;3. Dockerfile-dev도 중요&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;개발용 이미지를 담당하는 Dockerfile-dev 파일과 배포용 이미지를 담당하는 Dockerfile 파일이 따로 존재한다는 점을&amp;nbsp;&lt;/p&gt;&lt;p&gt;꼭 기억해야 합니다. 간혹 Dockerfile만 고치면서 개발 환경에서 ‘외않돼?’라고 생각한 경우가 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;4. 데이터베이스 내용도 지우고 싶을 때&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker-compose down --volume : 깔끔하게 초기화 된다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Dockfile-dev에 관하여(불필요한 운영환경설정 명령어 생략)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;FROM python:3&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;RUN apt-get update &amp;amp;&amp;amp; apt-get -y install \&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; libpq-dev&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;WORKDIR /app&lt;/p&gt;&lt;p&gt;ADD&amp;nbsp; &amp;nbsp; ./requirements.txt&amp;nbsp; &amp;nbsp;/app/&lt;/p&gt;&lt;p&gt;RUN&amp;nbsp; &amp;nbsp; pip install -r requirements.txt&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ADD&amp;nbsp; &amp;nbsp; ./djangosample&amp;nbsp; &amp;nbsp;/app/djangosample/&amp;nbsp;&lt;/p&gt;&lt;p&gt;// 해당 명령어 때문에, 로컬 프로젝트 소스 폴더와 컨테이너 내 소스폴더의 격리가 시작되는 것!(개발 중에는 필요 없음)&lt;/p&gt;&lt;p&gt;# ADD&amp;nbsp; &amp;nbsp; ./manage.py&amp;nbsp; &amp;nbsp; &amp;nbsp; /app/&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# CMD [&quot;python&quot;, &quot;manage.py&quot;, &quot;runserver&quot;, &quot;0:8000&quot;]&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// CMD: 도커 컴포즈의 command 속성으로 관리하는 편이 더 쉽기 때문에 생략&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 영구 db 저장소를 로컬에 맡기지 않고, Docker에 맡기기&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. Docker 볼륨을 생성한다.&lt;/p&gt;&lt;p&gt;볼륨은 도커가 관리하는 가상 디스크라고 생각&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. db 서비스 선언부 안에 volumes 항목을 넣고&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;- 가상디스크_이름 : 컨테이너_속_디렉터리처럼 지정&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;3. 이후로는 모든 데이터베이스 데이터가&amp;nbsp; django_sample_db_dev 볼륨에 저장됨&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;version: &#39;3&#39;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 변경 부분!&lt;/p&gt;&lt;p&gt;volumes:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//Docker 가상 디스크 생성&lt;/p&gt;&lt;p&gt;&amp;nbsp; django_sample_db_dev: {}&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;services:&lt;/p&gt;&lt;p&gt;&amp;nbsp; db:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; image: postgres&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; volumes:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; # 여기도!&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - django_sample_db_dev:/var/lib/postgresql/data // 가상 디스크로 마운트&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; environment:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ...&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;4. 가상 디스크 조회하기&lt;/p&gt;&lt;p&gt;docker volume ls&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;5. 가상 디스크 삭제하기&lt;/p&gt;&lt;p&gt;docker volume rm django_sample_db_dev&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 디버깅&lt;/p&gt;&lt;p&gt;1. 앱 서버가 데이터베이스를 못찾는 경우&lt;/p&gt;&lt;p&gt;- 첫 실행시 데이터베이스가 실행된 후 초기화 전에 앱서버가 실행되서 발생&lt;/p&gt;&lt;p&gt;- 가장 간단한 해결 방법은 서비스를 중지하고 다시 실행하는 것이지만 근본적인 해결책은 아님&lt;/p&gt;&lt;p&gt;- 이를 위해 wait-for-it.sh이라는 셸 스크립트를 사용&lt;/p&gt;&lt;p&gt;- 이 스크립트를 도커 이미지 안에 넣고, 이미지 실행 명령 앞에 붙여주면 됩니다.&lt;/p&gt;&lt;p&gt;./compose/django/Dockerfile-dev 파일의 마지막 부분에 다음 내용을 추가&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;ADD&amp;nbsp; &amp;nbsp; https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;- docker-compose.yml 내 수정&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;services:&lt;/p&gt;&lt;p&gt;&amp;nbsp; django:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; command:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - bash&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - -c&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - |&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /wait-for-it.sh db:5432 -t 10 // db 서비스의 5432 포트가 사용 가능할 때까지 기다린 후 앱 서버 실행&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; python manage.py runserver 0:8000&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 출처&lt;/p&gt;&lt;p&gt;https://www.44bits.io/ko/post/almost-perfect-development-environment-with-docker-and-docker-compose#%EB%8F%84%EC%BB%A4%EA%B0%80-%EB%B3%84%EB%A1%9C-%ED%8E%B8%ED%95%98%EC%A7%84-%EC%95%8A%EB%84%A4%EC%9A%94&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker : 서버 인프라를 VM 기반에서 Container 중심으로&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2013년 등장한 도커[Docker]는 인프라 세계를 컨테이너[Container] 세상으로 바꿔버렸습니다. 수많은 애플리케이션이 컨테이너로 배포되고 도커파일을 만들어 이미지를 빌드하고 컨테이너를 배포하는 게 흔한 개발 프로세스가 되었습니다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/3947158218591986900/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/03/docker-docker_54.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/3947158218591986900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/3947158218591986900'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/03/docker-docker_54.html' title='[Docker] Docker 사용법'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-5700024441074019338</id><published>2023-03-30T02:58:00.004-07:00</published><updated>2023-03-30T02:58:20.668-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><title type='text'>[Docker ] Docker 실습</title><content type='html'>&lt;p&gt;&amp;nbsp;https://sddev.tistory.com/218&lt;/p&gt;&lt;p&gt;위 링크 내용을 가져와서 내용 습득을 위해 다시 한번 정리한 것입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[Docker ] Docker 실습&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 설치&lt;/p&gt;&lt;p&gt;공식 사이트 주소 : https://www.docker.com/get-started&lt;/p&gt;&lt;p&gt;Desktop 버전 설치, Community로도 왠만한 기능은 사용 가능&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Dockerfile 작성하기&lt;/p&gt;&lt;p&gt;@ Dockerfile 만드는 순서&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1.베이스 이미지를 명시하기(파일 스냅샷에 해당)&lt;/p&gt;&lt;p&gt;2.추가적으로 필요한 파일을 다운 받기 위한 몇가지 명령어를 명시&lt;/p&gt;&lt;p&gt;3.컨테이너 시작시 실행 될 명령어를 명시&lt;/p&gt;&lt;p&gt;- FROM&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 생성할 이미지의 베이스가 될 이미지를 뜻합니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; FROM 명령어는 Dockerfile을 작성할 때 반드시 한 번 이상 입력해야 합니다.&lt;/p&gt;&lt;p&gt;- MAINTAINER&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 이미지를 생성한 개발자 정보를 나타냅니다.&lt;/p&gt;&lt;p&gt;- RUN&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행합니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; RUN 명령어에 [&quot;/bin/bash&quot;, &quot;echo hello&quot; &amp;gt;&amp;gt; test.html&quot;] 같이 입력하면&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; /bin/bash 셸을 이용해 &#39;echo hello &amp;gt;&amp;gt; test2.html&#39;을 실행한다는 뜻입니다.&lt;/p&gt;&lt;p&gt;- ADD&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 파일을 이미지에 추가합니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Dockerfile이 위치한 디렉터리에서 파일을 가져옵니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ADD &amp;lt;DockerFile 경로 기준 파일 상대경로&amp;gt; &amp;lt;컨테이너 내 폴더 경로&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ex) ADD test.html /var/www/html 이라면 Dockerfile과 같은 디렉토리에 있는 test.html 파일을&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 이미지 내부의 /var/www/html에 추가한다는 뜻입니다.&lt;/p&gt;&lt;p&gt;- WORKDIR&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 명령어를 실행할 디렉터리를 나타냅니다. 배시 쉘에서 cd 명령어를 입력하는 것과 같은 기능을 합니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 즉, 컨테이너 내부에서 작동을 합니다.&lt;/p&gt;&lt;p&gt;- EXPOSE&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Dockerfile의 빌드로 생성된 이미지에서 노출할 포트를 설정합니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 그러나 EXPOSE를 설정한 이미지로 컨테이너를 생성했다고 해서 반드시 이 포트가 호스트의 포트와 바인딩되는 것은&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 아니며, 단지 컨테이너의 80번 포트를 사용할 것임을 나타내는 것뿐입니다.&lt;/p&gt;&lt;p&gt;- CMD&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; CMD는 컨테이너가 시작될 때마다 실행할 명령어를 설정하며, Dockerfile에서 한 번만 사용할 수 있습니다.&lt;/p&gt;&lt;p&gt;- ADD, COPY&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ADD와 COPY는 큰 차이점이 없는 것처럼 보입니다. 하지만 차이점이 존재합니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; COPY는 로컬 디렉터리에서 읽어 들인 컨텍스트로부터 이미지에 파일을 복사하는 역할을 합니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ADD는 외부 URL 및 tar 파일에서도 파일을 추가할 수 있다는 점이 다릅니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ADD를 사용하는 것은 그다지 권장하지 않습니다.&lt;/p&gt;&lt;p&gt;- ENTRYPOINT, CMD&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ENTRYPOINT, CMD는 역할 자체는 비슷하지만 서로 다른 역할을 담당하는 명령어입니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 위의는 entrypoint를 사용하지 않은 경우입니다. 이 때는 /bin/bash에 접속한 것을 볼 수 있습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 이번에는 entrypoint를 사용하였습니다. 이 때는 /bin/bash를 출력한 것을 볼 수 있습니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 즉 둘 다 컨테이너가 시작될 때 수행할 명령을 지정한다는 점에서 같지만, entrypoint는 커맨드를 인자로 받아&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 사용할 수 있는 스크립트의 역할을 할 수 있다는 점에서 다릅니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Dockerfile 작성&lt;/p&gt;&lt;p&gt;# 베이스 이미지는 ubuntu:18.04 를 사용&lt;/p&gt;&lt;p&gt;FROM ubuntu:18.04&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 이미지 생성한 개발자 정보&lt;/p&gt;&lt;p&gt;MAINTAINER sddev1002 &amp;lt;sddev1002@gmail.com&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 명령어 실행(일반 텍스트)&lt;/p&gt;&lt;p&gt;RUN apt-get update&lt;/p&gt;&lt;p&gt;RUN apt-get install -y apache2 # Install Apache web server (Only &#39;yes&#39;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 로컬 파일 추가&lt;/p&gt;&lt;p&gt;ADD test.html /var/www/html&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 컨테이너 내 명령어 실행될 경로 지정&lt;/p&gt;&lt;p&gt;WORKDIR /var/www/html&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 명령어 실행(리스트 형태)&lt;/p&gt;&lt;p&gt;RUN [&quot;/bin/bash&quot;, &quot;-c&quot;, &quot;echo hello &amp;gt;&amp;gt; test2.html&quot;]&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 컨테이너를 80번 포트로 설정 (외부 노출)&lt;/p&gt;&lt;p&gt;EXPOSE 80&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# apache 서버가 죽지 않고 백그라운드로 돌아가기 위해서 아래의 명령어 실행&lt;/p&gt;&lt;p&gt;# 컨테이너 생성 후, apachectl -D FOREGROUND 명령어가 실행됨&lt;/p&gt;&lt;p&gt;CMD [&quot;apachectl&quot;, &quot;-D&quot;, &quot;FOREGROUND&quot;]&lt;/p&gt;&lt;p&gt;# CMD apachectl -D FOREGROUND&lt;/p&gt;&lt;p&gt;^z&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Dockerfile로 이미지 만들기&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# dockerfile이 존재하는 폴더로 이동&lt;/p&gt;&lt;p&gt;docker build -t &amp;lt;이미지명&amp;gt; .&lt;/p&gt;&lt;p&gt;docker images # 생성된 이미지 목록 조회&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;해당 Dockerfile이 있는 위치에서 위의 명령어를 입력하면 &amp;lt;이미지명&amp;gt; 이라는 이름의 Image가 생성된다.&lt;/p&gt;&lt;p&gt;.은 Dockerfile이 존재하는 현재 폴더 위치를 의미한다.&lt;/p&gt;&lt;p&gt;-t : tag의 약자로, 이미지에 대한 이름을 tag로 지정할 수 있다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 이미지로 컨테이너 생성 및 실행하기&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/5700024441074019338/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/03/docker-docker_39.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/5700024441074019338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/5700024441074019338'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/03/docker-docker_39.html' title='[Docker ] Docker 실습'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-6198624675955432076</id><published>2023-03-30T02:57:00.002-07:00</published><updated>2023-03-30T03:00:11.272-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><title type='text'>[Docker] Docker 명령어 핵심만 이해하기</title><content type='html'>&lt;p&gt;&amp;nbsp;https://sddev.tistory.com/126&lt;/p&gt;&lt;p&gt;위 링크 내용을 가져와서 내용 습득을 위해 다시 한번 정리한 것입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 명령어 핵심만 이해하기&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;추가 Windows docker desktop 에서 해당 콘테이너 실행하고 Container 탭에서 이름을 선택하면&lt;/p&gt;&lt;p&gt;&amp;nbsp;Logs, Inspect, Terminal, Files, Stats 등 하부 항목 등이 추가로 확인 가능하니 참고.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker images&lt;/p&gt;&lt;p&gt;docker 내에 이미지 목록 조회&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker ps -a&lt;/p&gt;&lt;p&gt;docker 내에 콘테이너 목록 조회&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 개요&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;기본적인 docker에 대한 동작 방식은 알고 있는 상태에서 명령어만 정리하겠다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. docker hub에서 이미지를 받을때는 pull 명령을 사용한다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;예를 들어 wildfly의 최신버전(latest)를 받을 경우 다음과 같이 한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker pull jboss/wildfly:latest&lt;/p&gt;&lt;p&gt;docker pull &amp;lt;이미지명&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker 내에 docker-hub로부터 이미지를 다운로드 하라.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. 내가 받은 모든 이미지들(예전에 ISO파일과 비슷하다고 보면 될 듯)의 목록을 볼 경우 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker images&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker 내에 지금까지 설치된 모든 이미지를 조회하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;3. 이미지 세부 정보를 확인할 때는 inspect 명령어를 사용한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker inspect jboss/wildfly:latest&lt;/p&gt;&lt;p&gt;docker inspect &amp;lt;이미지명&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;해당 이미지의 상세 정보를 조회하라.(os, cpu 등등이 표시된다.)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;세부 정보는 json 문자열 형태로 보여지며 주요 정보로는 이미지 ID, 생성일, Docker 버전, 이미지 생성자, CPU 등을&amp;nbsp;&lt;/p&gt;&lt;p&gt;제공한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;정보가 json 문자열 형태로 길게 나오기때문에 만약 특정 정보를 보고자 할때는 다음과 같이 format 옵션을&amp;nbsp;&lt;/p&gt;&lt;p&gt;주어 보고자 하는 항목을 지정하면 그 항목에 대해서만 볼 수 있다. 예를 들어&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker inspect --format=&quot;{{ .Os}}&quot; jboss/wildfly:latest&lt;/p&gt;&lt;p&gt;docker inspect --format=&quot;{{ .Config.Hostname}}&quot; jboss/wildfly:latest&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;4. 이미지를 삭제할때는 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker rmi jboss/wildfly:latest&lt;/p&gt;&lt;p&gt;docker rmi &amp;lt;이미지명&amp;gt;&lt;/p&gt;&lt;p&gt;docker 내에서 해당 이미지를 삭제하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;5. docker 이미지를 받았으면 이제 이 이미지를 가지고 하나의 컨테이너를 생성해서 실행시키도록 한다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이해하기 쉽게끔 설명하자면 프로그래밍에서 얘기하는 클래스와 객체로 설명하면 이해하기 쉬울듯 하다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A라는 클래스를 이용해서 B, C라는 객체를 생성할 때..&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;클래스 -&amp;gt; 이미지&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;객체&amp;nbsp; &amp;nbsp; -&amp;gt; 컨테이너&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A B = new A(); // 이 시점부터 실질적으로, 독립적인 공간이 생성&lt;/p&gt;&lt;p&gt;A C = new A();&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A라는 클래스를 이용해서 만든 객체 b와 c가 있지만 이 b와 c는 서로를 간섭하지는 않는다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이것을 docker에 비춰보면 클래스는 이미지가 되고 객체는 컨테이너가 된다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;필요성에 따라 이미지를 이용해서 0개 이상의 컨테이너를 만들수 있지만 이렇게 만들어진 컨테이너들은&amp;nbsp;&lt;/p&gt;&lt;p&gt;서로 독립적인 공간이 되어 서로 간섭하지를 않게 된다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;컨테이너의 라이프 사이클 : create(생성) -&amp;gt; start(시작) -&amp;gt; stop(중지) -&amp;gt; rm(삭제)&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;- docker create &amp;lt;신규 컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;- docker start &amp;lt;컨테이너명&amp;gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;- docker create &amp;amp; start &amp;lt;컨테이너명&amp;gt; = docker run &amp;lt;신규 컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;- docker stop &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;- docker end &amp;amp; start &amp;lt;컨테이너명&amp;gt; = docker restart &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;- docker end &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;- docker rm &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;6. docker에서 컨테이너를 생성하면서 동시에 시작할때는 run을 사용한다. wildfly를 예로 들자면 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker run -it --name &quot;wildfly&quot; -p 8080:8080 jboss/wildfly:latest&lt;/p&gt;&lt;p&gt;docker run -it --name &amp;lt;신규 컨테이너명&amp;gt; -p &amp;lt;외부HOST포트&amp;gt;:&amp;lt;컨테이너 내 포트&amp;gt; &amp;lt;이미지명&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;해당 이미지로 컨테이너를 생성하고, 시작하되, 포어그라운드(-it)로 실행하라. (현재 cmd 창에서는 컨테이너내 실행 결과들을 받아 볼 수 있음)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;run 명령어를 사용하면서 같이 사용된 옵션에 대해 설명을 하자면&amp;nbsp;&lt;/p&gt;&lt;p&gt;-i 옵션은 컨테이너 표준 입력을 연다는 뜻이고, -t는 tty(단말 디바이스)를 사용한다는 의미이다.&lt;/p&gt;&lt;p&gt;이 둘을 묶어서 -it로 사용한 것이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;-i는 interactive하게 컨테이너와 소통하겠다. -t는 tty를 사용한다는 뜻,&amp;nbsp;&lt;/p&gt;&lt;p&gt;즉 터미널과 비슷한 환경을 조성해주는 것&lt;/p&gt;&lt;p&gt;(-it 명령어가 없으면, 해당 컨테이너를 생성하고 실행하는 것으로만 그칠 것이면, 굳이 필요없다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;생성 후 cmd와 비슷한 명령어를 통해 컨테이너 내의 작업을 하길 원한다면 반드시 붙여야된다.)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;--name 옵션을 주면 해당 컨테이너에 대해 특별한 이름을 부여하는 옵션이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;컨테이너를 start 명령어로 시작하거나 stop 명령어를 이용해서 종료할때 대상 컨테이너를 지정하기 위해&amp;nbsp;&lt;/p&gt;&lt;p&gt;컨테이너 ID를 입력해야 하는데 이 ID라는게 의미가 없는 숫자/문자가 조합된 문자열이라 타이핑하기 어렵다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이러한 상황을 좀더 쉽게 사용하게 하기 위해 --name 옵션을 주어 의미있는 문자열을 지정함으로써&amp;nbsp;&lt;/p&gt;&lt;p&gt;차후에 start, stop 명령어를 사용할때 그 문자열을 사용하여 해당 명령어를 쉽게 실행할 수 있다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;-p는 호스트와 컨테이너 간의 포트를 연결하는 옵션이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;wildfly는 8080 포트를 이용해서 통신하게 되는데 이것은 어디까지나 컨테이너의 8080 포트를 열은 것이기 때문에&amp;nbsp;&lt;/p&gt;&lt;p&gt;우리가 테스트하기위해 브라우저에서 http://localhost:8080을 입력해도 동작이 이루어지지 않는다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이로 인해 호스트의 8080 포트를 컨테이너의 8080 포트와 연결해야 제대로 된 동작을 할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;한가지 더 첨언을 하자면 컨테이너가 8080 포트를 열었다고 해서 호스트도 반드시 8080 포트를 열으라는 법은 없다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;예를 들어 wildfly 컨테이너를 2개 이상 운영하는데 두 컨테이너가 모두 8080 포트를 열어도 문제가 되는 것은 없다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그러나 이 두 포트를 모두 호스트의 8080 포트에 연결할 수는 없다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;즉 둘 중 하나의 컨테이너는 -p 8081:8080 이런 식으로 호스트의 8081 포트를 컨테이너의 8080 포트로 열어서&amp;nbsp;&lt;/p&gt;&lt;p&gt;동작하게끔 해야한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;7. 6번의 과정으로 실행을 하게 되면 docker의 foreground로 실행하는 것이기 때문에&amp;nbsp;&lt;/p&gt;&lt;p&gt;이런 식으로의 실행은 추천하지 않는다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;즉 다른 컨테이너를 시작할려면 다시 쉘 창을 열어서 docker 관련 명령을 실행해야 하기 때문이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;대신 foreground에서 실행시키는 것이기 때문에 컨테이너를 중지할려면 ctrl-c를 눌러 중지할 수 있으며&amp;nbsp;&lt;/p&gt;&lt;p&gt;관련 콘솔 로그 내용도 바로 확인 할 수 있는 장점은 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그러나 docker로 실행되는 것이 WAS나 DB 서버 같은 서버용 프로그램인것을 감안하면 background로 실행되는 것이 좋다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;8. 7번에서 설명한대로 background로 컨테이너가 실행되게끔 할려면 -d 옵션을 붙이면 된다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker run -d --name &quot;wildfly&quot; -p 8080:8080 jboss/wildfly:latest&amp;nbsp;&lt;/p&gt;&lt;p&gt;docker run -d --name &amp;lt;신규 컨테이너명&amp;gt; -p &amp;lt;호스트 포트번호&amp;gt;:&amp;lt;컨테이너 포트번호&amp;gt; &amp;lt;이미지명&amp;gt;&lt;/p&gt;&lt;p&gt;해당 이미지로 컨테이너를 생성하고, 시작하되, 백그라운드(-d)로 실행하라.&amp;nbsp;&lt;/p&gt;&lt;p&gt;(현재 cmd 창에서는 아무것도 표시되지 않음)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// -d가 사용되는 경우, -it는 필요없다.&lt;/p&gt;&lt;p&gt;// -it 또는 -d가 주로 사용된다고 생각하자&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;6번에서 설명했을때는 -it옵션을 붙였으나 여기서는 background로 실행하는 것이기 때문에&amp;nbsp;&lt;/p&gt;&lt;p&gt;컨테이너 표준입력을 사용할 수가 없다. 그걸 제외한 나머지 옵션은 동일하다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;그러나 이렇게 실행하면 6번에서 컨테이너가 보여주는 로그들을 볼 수 없는 문제가 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이를 볼려면 logs 명령어를 사용하면 된다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker logs -f wildfly&lt;/p&gt;&lt;p&gt;docker logs -f &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;해당 컨테이너의 로그를 현재 cmd 창에 보여라.(-f는 실시간)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;-f 옵션은 linux 에서 tail 명령 사용했을때 -f 사용한 것을 생각하면 된다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;즉 로그를 계속 연속성으로 보여주는 것으로 이해하면 된다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;뒤에 wildfly가 붙은 것은 우리가 docker run을 이용해서 컨테이너를 실행할때 --name 옵션을 이용해서 주었던&amp;nbsp;&lt;/p&gt;&lt;p&gt;그 wildfly이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이렇게 컨테이너를 run 명령어를 이용해서 실행할때 --name 옵션으로 별칭 준것을 docker 관련 명령 실행시&amp;nbsp;&lt;/p&gt;&lt;p&gt;특정 컨테이너를 지칭하는데 사용함으로써 편리함을 준다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;9. 컨테이너 안에는 os가 있다는 것이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;즉 os 안에 관련 프로그램이 설치되어 있는 개념인 것이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이 부분은 나중에 build를 공부하면서 확연히 알게 되었다.&lt;/p&gt;&lt;p&gt;즉 기본 베이스 이미지를 centos 같은 리눅스 이미지로 삼은뒤 여기에 apache를 yum 명령어로 설치하면서&amp;nbsp;&lt;/p&gt;&lt;p&gt;이미지 만드는 법을 알게 되었다&amp;nbsp;&lt;/p&gt;&lt;p&gt;물론 베이스 이미지를 centos 같은 os 이미지가 아니라&amp;nbsp; wildfly 이미지를 사용할 수 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그렇다해도 wildfly에 centos가 이미 있기 때문에 결국 wildfly 이미지에 있는 centos 를 이용하는 것임에는&lt;/p&gt;&lt;p&gt;변함이 없다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이러한 개념이기 때문에 해당 컨테이너는 독자적인 OS와 그에 따른 환경변수를 가지고 실행할 수가 있는것이며&amp;nbsp;&lt;/p&gt;&lt;p&gt;서로간의 컨테이너에 영향을 주지 않고 독립적으로 움직이게 되는 것이다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker 이미지는 os가 포함이 되어 있는 0개 이상의 프로그램이 설치되어 있는 이미지이다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;10. 9번에서 설명했다시피 이미지는 자체적으로 OS가 포함되어 있다고 했다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그렇기 때문에 우리는 컨테이너가 실행중일때 이 컨테이너를 구동시키는 기반이 되는 OS에 접속할 수가 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;즉 우리가 wildfly 이미지를 이용하여 컨테이너를 실행중일때 이 컨테이너의 OS에 연결할 수 있다는 것이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이것은 나름 작업(?)적인 차원에서 중요한 의미가 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;예를 들어 우리가 wildfly에서 구동중인 web application을 만든다고 가정해보자.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그러면 파일 업로드 기능을 넣어야 하는데 파일 업로드를 하게 되면 OS에서 관리되는 디렉토리 중 하나에&amp;nbsp;&lt;/p&gt;&lt;p&gt;사용자가 업로드한 파일이 있어야 하며 그러한 디렉토리를 만들어놔야 한다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;그러면 이 디렉토리를 만들려면 wildfly 컨테이너의 os 쉘에 접근해서 디렉토리를 만드는 명령(mkdir)을 실행해야 한다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이러한 OS 쪽의 작업을 하거나 또는 wildfly의 설정파일(예를 들면 standalone.xml)을 수정할 수 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;그리고 이렇게 변경이 된 내용이 있는 컨테이너를 docker commit 명령을 이용해서 새로운 이미지로 만들어&amp;nbsp;&lt;/p&gt;&lt;p&gt;이를 다른 사람에게 배포할 수 있다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;서론이 길었는데 이 기능을 수행하는것에 대해 설명하도록 하겠다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;먼저 경우를 분리해서 생각해야 할 부분이 있는데 우리가 컨테이너를 실행시킬때 /bin/bash 같은 쉘을 실행시킨 상황과&amp;nbsp;&lt;/p&gt;&lt;p&gt;그렇지 않은 상황으로 분리해야한다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;/bin/bash를 실행시켜서 현재 컨테이너가 bash shell이 실행중인 상황이면 docker의 attach 명령을 이용해서&amp;nbsp;&lt;/p&gt;&lt;p&gt;접속하면 된다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker attach wildfly&amp;nbsp;&lt;/p&gt;&lt;p&gt;docker attach &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;해당 컨테이너에 접속하고, 해당 프로세스 화면을 보여줘라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이러면 bash shell 에 접속하여 shell 명령어를 실행시킬수 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;여기서는 컨테이너 이름을 지칭하기 위해 wildfly를 썼지만 실제로 wildfly는 이렇게 명령해도 접속이 되질 않는다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;왜냐면 wildfly는 bash shell을 실행시키지 않고 컨테이너를 띄우기 때문이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;때문에 attach 명령으로 접속 시도를 해도 동작이 되질 않는다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;또한 백그라운드로 실행시킨 컨테이너의 경우도 마찬가지이다.&lt;/p&gt;&lt;p&gt;(왜 그런지는 곰곰히 생각해보면 이해하기 쉽다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;우리가 background로 컨테이너를 실행시킨다는건 docker 명령어를 실제로 내리는 shell 창에서 억세스하는 것이 아니라&amp;nbsp;&lt;/p&gt;&lt;p&gt;말그대로 background로 돌리는 것인데 거기서 shell 명령을 실행시키는 /bin/bash가 실행될리가 없잖은가?)&amp;nbsp;&lt;/p&gt;&lt;p&gt;이렇게 /bin/bash 를 실행시키지 않고 시작한 컨테이너나 또는 background에서 실행중인 컨테이너를 접속하기 위해서는&amp;nbsp;&lt;/p&gt;&lt;p&gt;exec 명령을 사용해서 /bin/bash를 실행시켜 접속하면 된다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker exec -it -u root wildfly /bin/bash&lt;/p&gt;&lt;p&gt;docker exec -it -u root &amp;lt;컨테이너명&amp;gt; &amp;lt;터미널 명령어&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;해당 컨테이너의 root 사용자권한으로 해당 터미널 명령어를 실행시켜라.&lt;/p&gt;&lt;p&gt;(/bin/bash 명령어란 리눅스계열에서, 터미널 쉘을 여는 명령어?)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이렇게 exec 명령을 통해 /bin/bash를 실행시켜서 bash shell 명령을 실행시킬수가 있게 된다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;-u는 os의 어떤 계정을 통해서 명령을 실행시킬것인지를 지정하는 것이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그러면 어떤 계정을 사용해야 하는가?&amp;nbsp;&lt;/p&gt;&lt;p&gt;그것은 해당 컨테이너의 docker 이미지를 build 하는데 사용된 Dockerfile의 소스를 보면 알 수 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;일반적으로 docker 이미지들은 github 에서 이미지 관련 파일들이 존재하여&amp;nbsp;&lt;/p&gt;&lt;p&gt;이를 github에서 빌드하여 docker hub에 배포되는 형태를 취하고 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그래서 이 Dockerfile의 소스를 볼려면 github을 봐야한다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;wildfly를 예로 들면 docker hub의 wildfly에 대한 페이지(https://hub.docker.com/r/jboss/wildfly/)를 가보면&amp;nbsp;&lt;/p&gt;&lt;p&gt;Source 항목에 github과 링크되어 있는 링크를 볼 수 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이를 클릭하면 github에 있는 해당 이미지를 빌드하는데 사용된 Dockerfile을 볼 수 있게 된다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이 Dockerfile 을 클릭해서 상세 내용을 보면 USER 란 항목이 있어 Dockerfile을 이용해 빌드하면서&amp;nbsp;&lt;/p&gt;&lt;p&gt;실행하게 되는 명령어를 수행하는 OS 계정을 언급하게 된다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;바로 이 USER 항목에 언급된 계정을 -u 옵션 뒤에 사용해주면 된다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;모든 docker 이미지가 root 계정을 사용하는 것은 아니기 때문에 이것을 확인하고 진행하기 바란다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;attach와 exec에 대한 추가 설명&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;위의 내용을 읽어보면 bash shell 기능을 위주로 설명했기때문에 현재 bash shell이 실행중인 컨테이너를 접속하여 할때는&lt;/p&gt;&lt;p&gt;&amp;nbsp;attach, bash shell 이 실행중이지 않은 컨테이너를 접속하려 할때는 exec를 사용하는 것으로 이해가 될 것 같아서&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;부가설명을 하고자 한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;attach는 현재 실행중인 컨테이너에 접속 한다고 보는 것이 맞다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;docker 이미지가 컨테이너로 생성되면서 run이 될때 이미지 가 내부적으로 특정 프로그램을 실행시킬수도 있고&amp;nbsp;&lt;/p&gt;&lt;p&gt;또는 run 명령을 내리는 시점에서 특정 프로그램을 실행 시키게도 할 수 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이때 bash shell 이 실행되도록 /bin/bash 를 실행시켜서 attach 시 바로 bash shell prompt가 보이게끔 할 수도 있다. 그러나 그렇지 않은 이미지도 있다. 예를 들어 위에서 언급했던 wildfly 이미지의 경우 이 이미지는 컨테이너로 올라가는 시점에 wildfly의 standalone.sh 스크립트가 실행시켜 wildfly가 구동되도록 하고 있기 때문에 콘솔 화면에서 wildfly의 로그가 올라오는 것을 볼 수 있다. 그래서 docker의 attach 명령을 이용해서 wildfly의 컨테이너를 접속하면 wildfly 구동되고 있는 상황에서 나오는 콘솔로그를 볼 수 있다. 또한 이 상태에서 ctrl-c를 클릭하면 wildfly 가 실행되는 것이 종료되는 것을 볼 수 있다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이에 반해 exec는 현재 실행중인 컨테이너에 특정 shell script를 실행하는 것이라고 보는게 맞다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;예를 들어 wildfly 이미지의 컨테이너가 wildfly란 이름으로 컨테이너가 실행되어 있는 상태에서&amp;nbsp;&lt;/p&gt;&lt;p&gt;docker exec -it wildfly /bin/bash 로 명령을 내리면 해당 컨테이너에 bash shell을 실행시키는 것이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그래서 bash shell prompt가 화면에 나오게 되는 것이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;만약 /bin/bash가 아는 사용자가 만든 별도 스크립트를 실행시키면 그 스크립트가 실행시키는 것이다&lt;/p&gt;&lt;p&gt;(exec 명령어를 사용할때 -it 옵션을 주었기 때문에 해당 명령의 실행 결과가 현재 보는 화면에 바로 보이게 된다)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;11. docker 에서 등록되어 있는 컨테이너 목록을 확인 하는 명령은 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker ps -a&amp;nbsp;&lt;/p&gt;&lt;p&gt;현재 docker에 등록된 모든 컨테이너 목록을 조회하라.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;-a 옵션을 빼고 docker ps 로 실행하게 되면 현재 동작중인 컨테이너만 보여주기 때문에&amp;nbsp;&lt;/p&gt;&lt;p&gt;중지되어 있는 컨테이너는 보여주지 않게 된다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그래서 -a 옵션을 항상 붙여서 중지되어 있는 것도 같이 확인하는 버릇(?)을 들이는 것이 좋다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;12.&amp;nbsp; docker에서 실행중인 각 컨테이너가 사용하는 CPU 및 메모리 점유율 등 컨테이너의 상태를 확인하기 위해서는&amp;nbsp;&lt;/p&gt;&lt;p&gt;다음의 명령을 사용한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker stats&lt;/p&gt;&lt;p&gt;현재 docker에 등록된 컨테이너의 CPU, 메모리 점유율, 상태를 조회하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;13. 중지되어 있는 컨테이너를 구동하는 명령은 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker start wildfly&lt;/p&gt;&lt;p&gt;docker start &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;중지되어 있던 해당 컨테이너를 구동하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;14. 실행중인 컨테이너를 중지시키는 명령은 다음과 같이 한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker stop wildfly&lt;/p&gt;&lt;p&gt;docker stop &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;현재 실행중인 해당 컨테이너를 중지하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;15. 컨테이너를 재시작할때의 명령은 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker restart wildfly&lt;/p&gt;&lt;p&gt;docker restart &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;현재 실행중인 해당 컨테이너를 재시작하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;16. 컨테이너를 삭제할때의 명령은 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker rm -f wildfly&lt;/p&gt;&lt;p&gt;docker rm -f &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;해당 컨테이너를 완전히 삭제하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;원래 컨테이너를 삭제할때는 현재 상태가 중지되어 있는 컨테이너만 삭제가 가능하기 때문에&amp;nbsp;&lt;/p&gt;&lt;p&gt;실행중인 컨테이너는 삭제를 할 수가 없다. 그러나 -f 옵션을 붙이면 실행중인 컨테이너도 삭제하게 된다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker rm $(docker ps -a -q)&lt;/p&gt;&lt;p&gt;현재 docker에 등록되어 있는 컨테이너 중 실행된 컨테이너를 제외하고 모두 삭제하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker rm -f $(docker ps -a -q)&lt;/p&gt;&lt;p&gt;현재 docker에 등록되어 있는 모든 컨테이너를 삭제하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;17. 현재 구동중인 컨테이너에서 실행 중인 프로세스를 모두 일시정지 시키고자 할 때는 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker pause wildfly&lt;/p&gt;&lt;p&gt;docker pause &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;해당 컨테이너에서 실행 중인 모든 프로세스를 일시중지하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;일시정지된 컨테이너를 docker ps 명령어를 이용해서 컨테이너 목록으로 확인해보면&amp;nbsp;&lt;/p&gt;&lt;p&gt;Status에 Paused로 나온다&lt;/p&gt;&lt;p&gt;(참고로 stop 명령을 이용해서 컨테이너를 중지시킨 경우 docker ps 명령을 이용해 목록을 확인해보면&amp;nbsp;&lt;/p&gt;&lt;p&gt;Status에 Exited로 나온다)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이렇게 일시정지된 컨테이너를 다시 재시작 시킬때는 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker unpause wildfly&lt;/p&gt;&lt;p&gt;docker unpause &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;일시중지였던 해당 컨테이너를 다시 정상화하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;18. 현재 구동중인 컨테이너에서 실행중인 프로세스를 확인할때는 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker top wildfly&lt;/p&gt;&lt;p&gt;docker top &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;해당 컨테이너의 실행중인 프로세스를 조회하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;linux에서 top 명령을 실행한것과 같은 유형의 결과물을 보여준다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;19. 구동중인 컨테이너에서 실행중인 프로세스가 이용중인 포트를 확인하고자 할때는 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker port wildfly&lt;/p&gt;&lt;p&gt;docker port &amp;lt;컨테이너명&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;해당 컨테이너에서 사용중인 포트를 조회하라&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;(ex)&lt;/p&gt;&lt;p&gt;8080/tcp -&amp;gt;0.0.0.0:8080&lt;/p&gt;&lt;p&gt;왼쪽 : 컨테이너의 포트 -&amp;gt; 8080 포트(왼쪽의 8080/tcp)를&lt;/p&gt;&lt;p&gt;오른쪽 : 호스트 컴퓨터(정확하게는 현재 내가 사용중인 OS)의 포트 -&amp;gt;8080 포트(0:.0.0.0:8080)와 연결되고 있음&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;20. 컨테이너와 호스트 컴퓨터 간의 파일 복사는 다음과 같이 한다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker cp wildfly:/opt/jboss/wildfly/standalone/configuration/standalone.xml D:/dockerimages&lt;/p&gt;&lt;p&gt;docker cp &amp;lt;컨테이너명&amp;gt;:&amp;lt;복사파일경로&amp;gt; &amp;lt;붙여넣을 폴더 로컬 경로&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;컨테이너의 파일을 로컬 경로로 복사하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker cp D:/dockerimages/standalone.xml wildfly:/opt/jboss/wildfly/standalone/configuration&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;docker cp &amp;lt;복사 로컬파일 경로&amp;gt; &amp;lt;컨테이너명&amp;gt;:&amp;lt;붙여넣을 컨테이너 경로&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;로컬 파일을 컨테이너 경로로 복사하라.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 출처&amp;nbsp;&lt;/p&gt;&lt;p&gt;https://zgundam.tistory.com/132&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/6198624675955432076/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/03/docker-docker_30.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/6198624675955432076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/6198624675955432076'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/03/docker-docker_30.html' title='[Docker] Docker 명령어 핵심만 이해하기'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-5151063349818953388</id><published>2023-03-30T02:56:00.001-07:00</published><updated>2023-03-30T03:00:28.682-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><title type='text'>[Docker] Docker 이론</title><content type='html'>&lt;p&gt;원본링크: https://sddev.tistory.com/118&lt;/p&gt;&lt;p&gt;위 링크 내용을 가져와서 내용 습득을 위해 다시 한번 정리한 것입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[Docker] Docker 이론&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker란?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Linux Container 기반의 가상화 플랫폼이다.&lt;/p&gt;&lt;p&gt;Docker는 애플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 소프트웨어 플랫폼입니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker는 소프트웨어를 컨테이너라는 표준화된 유닛으로 패키징하며, 이 컨테이너에는 라이브러리, 시스템 도구, 코드, 런타임 등 소프트웨어를 실행하는 데 필요한 모든 것이 포함되어 있습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker를 사용하면 환경에 구애받지 않고 애플리케이션을 신속하게 배포 및 확장할 수 있으며 코드가 문제없이 실행될 것임을 확신할 수 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker의 작동 방식&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker는 코드를 실행하는 표준 방식을 제공합니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Docker는 컨테이너를 위한 운영 체제입니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;가상 머신[VM]이 서버 하드웨어를 가상화하는 방식과 비슷하게(직접 관리해야 하는 필요성 제거)&amp;nbsp; 컨테이너[Container]는 서버 운영 체제를 가상화합니다.&lt;/p&gt;&lt;p&gt;Docker는 각 서버에 설치되며 컨테이너를 구축, 시작 또는 중단하는 데 사용할 수 있는 간단한 명령을 제공합니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker를 사용하는 이유&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker를 사용하지 않고, 개별 local에 Redis, Mysql과 같은 프로그램을 설치하려면,&amp;nbsp;&lt;/p&gt;&lt;p&gt;환경별로 설치 중에 다양한 에러가 발생한다.&lt;/p&gt;&lt;p&gt;Docker를 설치하면, Docker Engine 상에서 어느 환경에서나 명령어 하나만으로 동일한 서비스를 설치하고, 쉽게 접근이 가능하다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker Container와 기존 VmWare VM 기술의 공통점 &amp;amp; 차이점&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;둘 다 격리된 리소스를 가진 실행 환경을 제공하지만,&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;VM은 HostOS와 별개인 GuestOS를 설치하여 동작하여 무겁고,&lt;/p&gt;&lt;p&gt;Docker Container는 별도의 OS 없이 HostOS의 커널을 공유하므로 실행이 가볍다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker: 어플리케이션을 실행할 때는 컨테이너 방식에서는 Host OS 위에 애플리케이션의 실행 패키지인 이미지를 배포하기만 하면 됩니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;VM: VM은 어플리케이션을 실행 하기 위해서 VM을 띄우고 자원을 할당한 다음,&amp;nbsp;&lt;/p&gt;&lt;p&gt;게스트 OS를 부팅하여 어플리케이션을 실행 해야 해서 훨씬 무겁고 복잡하게 실행해야 합니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;공통점: 도커 컨테이너와 가상 머신은 기본 하드웨어에서 격리된 환경 내에 애플리케이션을 배치하는 방법입니다.&lt;/p&gt;&lt;p&gt;차이점: 가장 큰 차이점은 격리된 환경을 얼마나 격리를 시키는지의 차이&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker Container는 커널은 공유하고 나머지 CPU, 메모리, 하드디스크는 컨테이너 안에 다 격리되어 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker Container의 격리 구현 원리&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 클라이언트와 Docker 서버는 Linux로 되어 있습니다.&lt;/p&gt;&lt;p&gt;Linux OS Kernel에서 제공하는 CGroup과 네임스페이스(Namespaces)을 활용하여 구현된다.&lt;/p&gt;&lt;p&gt;이것들은 Container와 호스트에서 실행되는 프로세스 사이에 벽을 만드는 리눅스 커널 기능들입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Linux Kernel의 C Group &amp;amp; 네임스페이스&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;C Group: CPU, 메모리, Network, HD I/O 등 프로세스 그룹의 시스템 리소스 사용량을 관리&lt;/p&gt;&lt;p&gt;어떤 애플리케이션 사용량이 너무 많다면 그 어플리케이션 같은 것을 C Group에 집어 넣어서&amp;nbsp;&lt;/p&gt;&lt;p&gt;CPU와 메모리 사용 제한 가능 (필요한 만큼만 할당해 줌)&lt;/p&gt;&lt;p&gt;네임스페이스: 하나의 시스템에서 프로세스를 격리시킬 수 있는 가상화 기술&lt;/p&gt;&lt;p&gt;(별개의 독립된 공간을 사용하는 것처럼 격리된 환경을 제공하는 경량 프로세스 가상화 기술)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker Container란?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 컨테이너는 Docker 이미지의 인스턴스로써,&lt;/p&gt;&lt;p&gt;어플리케이션이 동작하기 위해서 필요한 요소(실행 파일, 어플리케이션 엔진 등)을 패키지화하고 격리하는 기술이다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;컨테이너란 호스트 OS상에 논리적인 구획(컨테이너)을 만들고, 어플리케이션을 작동시키기 위해 필요한 라이브러리나&amp;nbsp;&lt;/p&gt;&lt;p&gt;어플리케이션 등을 하나로 모아, 마치 별도의 서버인 것처럼 사용할 수 있게 만든 것이다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker Image란?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 컨테이너를 만들기 위해 필요한 설정이나 종속성들을 갖고 있는 소프트웨어 패키지이다.&lt;/p&gt;&lt;p&gt;Docker 이미지는 Dockerhub에 다른 사람들이 만들어놓은 이미지를 다운받아 사용할 수도 있고&amp;nbsp;&lt;/p&gt;&lt;p&gt;직접 이미지를 만들어 사용할 수도 있음&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 이미지는 컨테이너 실행에 필요한 파일과 설정값등을 포함하고 있다.&lt;/p&gt;&lt;p&gt;응용 프로그램을 실행하는데 필요한 모든 것을 포함하고 있습니다.&lt;/p&gt;&lt;p&gt;- 컨테이너가 시작 될 때 실행되는 명령어 (Dockerfile로 관리)&lt;/p&gt;&lt;p&gt;- 파일 스냅샷 (ex: 카카오톡이라면 카카오톡을 실행하는데 필요한 파일) - 디렉토리나 파일을 압축시킨 스냅샷&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker Layer란?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;기존 Docker Image 에 추가적인 파일이 필요할 때 다시 다운로드받는 방법이 아닌&lt;/p&gt;&lt;p&gt;해당 변경 내용만을 추가하기 위한 개념이다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;도커의 이미지가 변할때마다 새롭게 다운받는다면 이미지의 용량이 크기에 비효율적이다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이를 해결하기 위해 Layer라는 개념을 이용한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이미지는 여러 개의 읽기 전용(read only) layer로 구성되고, 파일이 추가되면 새로운 Layer가 생성됨.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그리고 도커는 여러 개의 Layer를 묶어서 하나의 파일시스템으로 사용할 수 있게 해준다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;DockerHub 및 개인 저장소에서 이미지를 공유할 때는 바뀐 부분(Layer = image)만 주고받기 가능하다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Dockerfile이란?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker Image를 만들기 위한 설정 파일이다.&lt;/p&gt;&lt;p&gt;컨테이너가 어떻게 행동해야 하는지에 대한 설정들을 정의하는 파일이다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;도커이미지 생성 과정에 대해 기술.&lt;/p&gt;&lt;p&gt;- 이미지를 빌드하려면 이미지를 만들고 실행하는 데 필요한 단계를 정의하는 간단한 구문&lt;/p&gt;&lt;p&gt;- Dockerfile의 각 명령어는 이미지에 레이어를 만듭니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Dockerfile을 변경하고 이미지를 다시 빌드하면 변경된 레이어 만 다시 빌드된다&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker Volume이란?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Container를 삭제하더라도, 로컬 Host PC 디렉토리에 파일이 남아있도록,&lt;/p&gt;&lt;p&gt;컨테이너 디렉토리가 로컬 디렉토리를 참조할 수 있도록 매핑해주는 기능이다.&lt;/p&gt;&lt;p&gt;컨테이너를 삭제하면, MySQL 컨테이너에 존재하던 데이터들이 다 삭제가 됩니다.&lt;/p&gt;&lt;p&gt;이렇게 데이터가 삭제되면 나중에 문제가 될 수 있기 때문에 컨테이너가 중지되더라도 데이터를 보존하는 것이 필요합니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이럴 때 사용하는 것이 Volume 입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker Compose란?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;멀티 Container 상황에서, 별도의 설정 없이 컨테이너간 네트워크 연결을 용이하게 해주고&lt;/p&gt;&lt;p&gt;멀티 컨테이너를 복합 관리할 수 있는 기능이다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker Compose를 사용하지 않고, NodeJS, Redis 컨테이너를 만들어서 컨테이너간 통신을 시도할 경우,&amp;nbsp;&lt;/p&gt;&lt;p&gt;개별로 생성된 컨테이너간 통신을 할 때, 아무런 설정을 해주지 않으면 상호 접근이 불가능하므로 에러가 발생&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;CLI 명령어에서 --link와 같은 것들을 이용할 수도 있으나,&amp;nbsp;&lt;/p&gt;&lt;p&gt;멀티 컨테이너 상황에서 쉽게 네트워크를 연결시켜주기 위해서는 Docker Compose를 이용하는 것이 좋다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker Compose를 사용하면 위와 같이 두 개의 컨테이너를 Service를 통해서 연결시켜줘서&amp;nbsp;&lt;/p&gt;&lt;p&gt;컨테이너 간의 통신을 할 수 있게 된다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 명령어를 하나하나 입력하는 것보다는 yml 파일에서 docker-compose를 이용해서 사용하는 것이 더 편리하다는 장점이 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker compose를 별도로 설치가 필요하고, docker-compose.yml 파일에서, dockerfile을 참조하여 build할 수도 있다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 가상화 VM 기술 설명&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;- 가상화 기술 나오기 전, 한대의 서버를 하나의 용도로만 사용, 남는 서버 공간 그대로 방치,&lt;/p&gt;&lt;p&gt;하나의 서버에 하나의 OS, 하나의 프로그램만을 운영, 안정적일 수 있지만 비효율적&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;- 하이퍼 바이저 기반의 가상화 등장, 논리적으로 공간을 분할하여 VM이라는 독립적인 가상 환경의 서버 이용 가능&lt;/p&gt;&lt;p&gt;하이퍼 바이저는 호스트 시스템에서 다수의 게스트 OS를 구동할 수 있는 소프트웨어,&lt;/p&gt;&lt;p&gt;하드웨어를 가상화하면서 하드웨어와 각각의 VM을 모니터링하는 중간 관리자&lt;/p&gt;&lt;p&gt;하이퍼바이저 아래에 기존 OS가 존재하고 그 위에 Guest OS가 존재하는 것을 볼 수 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;- 하이퍼바이저에 의해 구동되는 VM은 각 VM마다 독립된 가상 하드웨어 자원을 할당 받음&lt;/p&gt;&lt;p&gt;논리적으로 분리 되어 있어서 한 VM에 오류가 발생해도 다른 VM으로 퍼지지 않는다는 장점이 있음&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;VMWare의 개별 VM들이 하이퍼 바이저 기반에서 동작하듯이, Docker의 Docker Container들은 Docker Engine 기반에서 동작한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker의 구성요소와 아키텍처&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker의 아키텍처란?&lt;/p&gt;&lt;p&gt;Docker는 Docker Client와 Docker Deamon(Server) 간의 Rest API를 통해 통신하며,&amp;nbsp;&lt;/p&gt;&lt;p&gt;Docker Resistry (Docker Hub)를 통해, 다양한 Docker Image를 쉽게 다운로드할 수 있도록 지원한다.&lt;/p&gt;&lt;p&gt;Docker는 클라이언트-서버 아키텍처이다. 도커 클라이언트와 도커 데몬이RestApi를 사용하여 통신한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker 데몬&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker Api 요청수신, 이미지,컨테이너,네트워크와 같은 도커 객체 및 도커 서비스 관리&lt;/p&gt;&lt;p&gt;Docker 클라이언트&lt;/p&gt;&lt;p&gt;Docker 사용자가 Docker와 상호작용하기 위한 방법. 기본적인 도커명령어를 통해서 Docker 데몬과 통신&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker 레지스트리&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Docker 이미지를 저장, Docker hub이라는 공용 레지스트리와 개인private한 레지스트리가 있다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;일반적으로 공용 레지스트리에서 실행&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; (cf) docker pull, docker run: 사용하면&amp;nbsp; 필수이미지 가져온다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; (cf) docker push: 레지스트리에 저장&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Docker 객체&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;도커 이미지: 도커 이미지는 컨테이너 실행에 필요한 파일과 설정값등을 포함하고 있다.&lt;/p&gt;&lt;p&gt;컨테이너 : 컨테이너는 도커 이미지의 실행 가능한 인스턴스입니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# 출처&lt;/p&gt;&lt;p&gt;- https://aws.amazon.com/ko/docker/&lt;/p&gt;&lt;p&gt;- https://devlog-wjdrbs96.tistory.com/278&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/5151063349818953388/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2023/03/docker-docker.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/5151063349818953388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/5151063349818953388'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2023/03/docker-docker.html' title='[Docker] Docker 이론'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-3119540208540685447</id><published>2022-01-27T00:07:00.004-08:00</published><updated>2022-01-27T00:07:45.355-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Adplus"/><category scheme="http://www.blogger.com/atom/ns#" term="WinDbg"/><category scheme="http://www.blogger.com/atom/ns#" term="디버깅"/><title type='text'>윈도우 프로그램 디버그, AdPlus</title><content type='html'>&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;참고.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;a href=&quot;http://m.egloos.zum.com/sweeper/v/2456134&quot;&gt;수까락의 프로그래밍 이야기 (zum.com)&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/3119540208540685447/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2022/01/adplus.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/3119540208540685447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/3119540208540685447'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2022/01/adplus.html' title='윈도우 프로그램 디버그, AdPlus'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-3008123163690548927</id><published>2022-01-20T00:08:00.004-08:00</published><updated>2022-01-20T00:08:33.993-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="온라인"/><category scheme="http://www.blogger.com/atom/ns#" term="정규식"/><category scheme="http://www.blogger.com/atom/ns#" term="테스트"/><title type='text'>정규식 관련 온라인 테스트 사이트</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;a href=&quot;https://regexr.com/6dm2n&quot;&gt;RegExr: Untitled 6dm2n&lt;/a&gt;&amp;nbsp;에서 테스트 해봄&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;검색용 정규식&lt;/p&gt;&lt;p&gt;(SetEffective)[\(\t\n\r]+(EFST_NOACTION_WAIT)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;테스트 텍스트&lt;/p&gt;&lt;p&gt;SetEffective(EFST_NOACTION_WAIT, 0);&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;SetEffective(&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;			&lt;/span&gt;EFST_NOACTION_WAIT, 0);&lt;/p&gt;&lt;p&gt;SetEffective(&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;EFST_NOACTION_WAIT, 0);&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;ResetEffective(EFST_NOACTION_WAIT, 0);&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;ResetEffective(&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;EFST_NOACTION_WAIT, 0)&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;참고1.&amp;nbsp;&lt;a href=&quot;https://sysops.tistory.com/174&quot;&gt;정규표현식(Regular Expression) 사이트 및 팁 (tistory.com)&lt;/a&gt;&lt;/p&gt;&lt;div style=&quot;background-color: white; color: #555555; font-family: &amp;quot;Spoqa Han Sans&amp;quot;, sans-serif; font-size: 15px; line-height: 28px; margin: 0px auto 28px; padding-bottom: 0px !important; padding-left: 0px; padding-right: 0px; padding-top: 0px !important; padding: 0px; text-align: left;&quot;&gt;참고2.&amp;nbsp;&lt;a href=&quot;https://hamait.tistory.com/342&quot; style=&quot;background-color: transparent;&quot;&gt;정규표현식 (Regex) 정리 (tistory.com)&lt;/a&gt;&lt;/div&gt;&lt;p style=&quot;background-color: white; color: #555555; font-family: &amp;quot;Spoqa Han Sans&amp;quot;, sans-serif; font-size: 15px; line-height: 28px; margin: 0px auto 28px; padding-bottom: 0px !important; padding-left: 0px; padding-right: 0px; padding-top: 0px !important; padding: 0px; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/3008123163690548927/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2022/01/blog-post.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/3008123163690548927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/3008123163690548927'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2022/01/blog-post.html' title='정규식 관련 온라인 테스트 사이트'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-207915159438851545</id><published>2022-01-10T21:46:00.008-08:00</published><updated>2022-01-10T21:52:05.801-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="c++"/><category scheme="http://www.blogger.com/atom/ns#" term="GetTickCount()"/><category scheme="http://www.blogger.com/atom/ns#" term="timeGetTime()"/><title type='text'>VS 2017:C++에서 timeGetTime() 과 GetTickCount() 결과값 비교(DWORD 로 같은 내용 반환)</title><content type='html'>&lt;div&gt;// timeGetTime() 과 GetTickCount() 다른 내용인 것 처럼 표시되어 있으나,&lt;/div&gt;&lt;div&gt;// 적어도, VS2017 에서는 같은 결과를 반납함.&amp;nbsp;&lt;/div&gt;&lt;div&gt;// 혹시, 다른 버전에서는 다른 결과를 반납하는지 확인 필요.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;#include &amp;lt;windows.h&amp;gt;&lt;span style=&quot;white-space: pre;&quot;&gt;					&lt;/span&gt;// GetTickCount()&lt;br /&gt;#pragma comment(lib, &quot;winmm.lib&quot;)&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;// timeGetTime()&lt;br /&gt;using DWORD = unsigned long;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;const DWORD curTime2 = timeGetTime();&lt;br /&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;std::cout &amp;lt;&amp;lt; &quot;timeGetTime(): &quot; &amp;lt;&amp;lt; curTime2 &amp;lt;&amp;lt; std::endl;&lt;br /&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;const DWORD curTime = GetTickCount();&lt;span style=&quot;white-space: pre;&quot;&gt;		&lt;/span&gt;//49.5일에 초기화문제 있슴. ULONGLONG GetTickCount64() 를 쓰는 것도 검토 해볼만함&lt;br /&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;std::cout &amp;lt;&amp;lt; &quot;GetTickCount(): &quot; &amp;lt;&amp;lt; curTime &amp;lt;&amp;lt; std::endl;&lt;br /&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;std::cout &amp;lt;&amp;lt; &quot;Press enter a key.&quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;std::getchar();&lt;br /&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;return 0;&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;실행 결과&lt;/div&gt;&lt;div&gt;&lt;div&gt;timeGetTime(): 15419953&lt;/div&gt;&lt;div&gt;GetTickCount(): 15419953&lt;/div&gt;&lt;div&gt;Press enter a key.&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/207915159438851545/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2022/01/vs-2017c-timegettime-gettickcount-dword.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/207915159438851545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/207915159438851545'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2022/01/vs-2017c-timegettime-gettickcount-dword.html' title='VS 2017:C++에서 timeGetTime() 과 GetTickCount() 결과값 비교(DWORD 로 같은 내용 반환)'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-808091920505795988</id><published>2021-08-13T21:35:00.005-07:00</published><updated>2021-08-13T21:35:51.969-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="close tab"/><category scheme="http://www.blogger.com/atom/ns#" term="excel"/><category scheme="http://www.blogger.com/atom/ns#" term="vbs"/><category scheme="http://www.blogger.com/atom/ns#" term="엑셀"/><title type='text'>엑셀 특정 탭 남기고 다 닫기 .vbs</title><content type='html'>&lt;p&gt;&amp;nbsp;엑셀 시작후&lt;/p&gt;&lt;p&gt;0. 작업할 시트를 염&lt;/p&gt;&lt;p&gt;1. alt + F11 누름&lt;/p&gt;&lt;p&gt;2. 왼쪽 트리에서 통합시트 를 선택 후 우클릭&lt;/p&gt;&lt;p&gt;3. 메뉴에서 삽입 &amp;gt; 모듈 선택&lt;/p&gt;&lt;p&gt;4. 아래 모듈 붙여 넣기 후 남겨놓을 시트 이름으로 변경후 실행&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Sub DeleteSheets1()&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Dim xWs As Worksheet&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Application.ScreenUpdating = False&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Application.DisplayAlerts = False&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; For Each xWs In Application.ActiveWorkbook.Worksheets&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; If xWs.Name &amp;lt;&amp;gt; &quot;Sheet8&quot; Then&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; xWs.Delete&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; End If&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Next&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Application.DisplayAlerts = True&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Application.ScreenUpdating = True&lt;/p&gt;&lt;p&gt;End Sub&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/808091920505795988/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2021/08/vbs.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/808091920505795988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/808091920505795988'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2021/08/vbs.html' title='엑셀 특정 탭 남기고 다 닫기 .vbs'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-8561496060217294603</id><published>2021-07-08T19:21:00.004-07:00</published><updated>2021-07-08T19:21:42.042-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cmd"/><category scheme="http://www.blogger.com/atom/ns#" term="윈도우10"/><category scheme="http://www.blogger.com/atom/ns#" term="주소창"/><category scheme="http://www.blogger.com/atom/ns#" term="탐색기"/><title type='text'>윈도우10팁 - 탐색기 주소창에 cmd 입력하면 cmd 창 이 똭~</title><content type='html'>&lt;p&gt;탐색기( Explorer Window)에서&lt;/p&gt;&lt;p&gt;주소 입력창에 전체 경로 표시 되는 곳에 마우스 입력하고&lt;/p&gt;&lt;p&gt;입력 상태로 바뀌면 주소 앞에 &#39;cmd&#39; 에 한칸 띄어쓰기 하면&lt;/p&gt;&lt;p&gt;cmd 창이 해당 위치로 바로 열림&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/8561496060217294603/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2021/07/10-cmd-cmd.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/8561496060217294603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/8561496060217294603'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2021/07/10-cmd-cmd.html' title='윈도우10팁 - 탐색기 주소창에 cmd 입력하면 cmd 창 이 똭~'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-8790051016540538146</id><published>2021-01-14T02:24:00.005-08:00</published><updated>2021-01-14T02:25:15.126-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="html 태그 제거"/><category scheme="http://www.blogger.com/atom/ns#" term="notepad++"/><category scheme="http://www.blogger.com/atom/ns#" term="정규식"/><title type='text'>Notepad++ 를 이용 WebPage 샘플 소스에서 html 태그 제거하기.</title><content type='html'>&lt;p&gt;크롬을 이용하여 웹페이지에서 해당 소스를 찾았는데, 복사 금지이면,&lt;/p&gt;&lt;p&gt;f12 를 눌러 개발자 도구창(?)을 선택하고,&lt;/p&gt;&lt;p&gt;영역 선택 버턴을 눌러서 원하는 소스가 있는 부분에서&lt;/p&gt;&lt;p&gt;가능하면 해당 영역을 전부 포함되는 가장작은&amp;nbsp; 영역을 선택함.&lt;/p&gt;&lt;p&gt;우측 html 에서 html 수정 내용을 왕창 가져와서 notepad++에 붙여넣기를 시전한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;lt;notepad++ 에 정규식을 이용한 내용 일괄 변경 기능 사용&amp;gt;&lt;/p&gt;&lt;p&gt;notepad++ 에서 ctrl + h&amp;nbsp; 를 눌러 replace 창에서 검색항목에 아래 항목을 입력하고&lt;/p&gt;&lt;p&gt;&quot;&amp;lt;[^&amp;gt;]+&amp;gt;&quot; &amp;lt;- 옆에 &quot;는 제거 해야함&lt;/p&gt;&lt;p&gt;정규식 옵션 항목 선택 후 replace all 버턴을 선택하면 거의 대부분의&lt;/p&gt;&lt;p&gt;html 태그 깔끔하게 제거 됨&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/8790051016540538146/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2021/01/notepad-webpage-html.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/8790051016540538146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/8790051016540538146'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2021/01/notepad-webpage-html.html' title='Notepad++ 를 이용 WebPage 샘플 소스에서 html 태그 제거하기.'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-4277194654882031986</id><published>2020-09-05T04:46:00.003-07:00</published><updated>2020-09-05T04:46:36.040-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="no hostkeys"/><category scheme="http://www.blogger.com/atom/ns#" term="ssh-server"/><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu"/><category scheme="http://www.blogger.com/atom/ns#" term="wsl2"/><title type='text'>[linux] start faied ssh server service</title><content type='html'>&lt;p&gt;$ sudo service ssh start&lt;/p&gt;&lt;p&gt;&amp;nbsp;* Starting OpenBSD Secure Shell server sshd&lt;/p&gt;&lt;p&gt;sshd: no hostkeys available -- exiting.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;/etc/ssh 폴더 아래에 ssh_host_* 파일이 없어서 발생하는 문제&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;$ ls /etc/ssh&lt;/p&gt;&lt;p&gt;total 552&lt;/p&gt;&lt;p&gt;moduli&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ssh_config&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ssh_config.d&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ssh_import_id&lt;/p&gt;&lt;p&gt;sshd_config&amp;nbsp; &amp;nbsp;sshd_config.d&lt;/p&gt;&lt;p&gt;$&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;$ sudo ssh-keygen -A&lt;/p&gt;&lt;p&gt;ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;$ ls /etc/ssh/&lt;/p&gt;&lt;p&gt;moduli&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ssh_host_dsa_key&amp;nbsp; &amp;nbsp; &amp;nbsp; ssh_host_ecdsa_key.pub&amp;nbsp; &amp;nbsp; ssh_host_rsa_key&amp;nbsp; &amp;nbsp; &amp;nbsp; sshd_config&lt;/p&gt;&lt;p&gt;ssh_config&amp;nbsp; &amp;nbsp; ssh_host_dsa_key.pub&amp;nbsp; ssh_host_ed25519_key&amp;nbsp; &amp;nbsp; &amp;nbsp; ssh_host_rsa_key.pub&amp;nbsp; sshd_config.d&lt;/p&gt;&lt;p&gt;ssh_config.d&amp;nbsp; ssh_host_ecdsa_key&amp;nbsp; &amp;nbsp; ssh_host_ed25519_key.pub&amp;nbsp; ssh_import_id&lt;/p&gt;&lt;p&gt;$&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/4277194654882031986/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2020/09/linux-start-faied-ssh-server-service.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/4277194654882031986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/4277194654882031986'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2020/09/linux-start-faied-ssh-server-service.html' title='[linux] start faied ssh server service'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-4870092884986558447</id><published>2020-08-08T06:12:00.007-07:00</published><updated>2020-08-14T23:15:10.667-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="c. c++"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="msvc"/><category scheme="http://www.blogger.com/atom/ns#" term="triplet"/><category scheme="http://www.blogger.com/atom/ns#" term="vcpkg"/><title type='text'>vcpkg - VisualC 용 package manager</title><content type='html'>&lt;p&gt;&amp;nbsp;node.js 의 npm 처럼 c는 왜 간편한 패키지 설치 관리자 같은게 없나 늘 의문 이었슴.&lt;/p&gt;&lt;p&gt;c#(.net)을 위한 nuget 이 있기는 했지만, 이건 c++ 용이 아니라 여러가지가 혼재 되어 있어서&lt;/p&gt;&lt;p&gt;사용하기 애매 하단 느낌이었는데, 자료 검색 중 발견 !!!!!!!&lt;/p&gt;&lt;p&gt;이미 많은 분들이 사용하고 있을 듯, 사용법은 기존 pkg manager 와 비슷&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/microsoft/vcpkg&quot;&gt;https://github.com/microsoft/vcpkg&lt;/a&gt;&lt;/p&gt;&lt;p&gt;위 git 웹이지 설명에는 라고 되어 있었슴.&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;C++ Library Manager for Windows, Linux, and MacOS&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face=&quot;&quot; style=&quot;color: #24292e;&quot;&gt;&lt;span style=&quot;background-color: #fafbfc;&quot;&gt;해당 페이지에 설치 방법에 대해 설명이 있으니, 가능한 자세히 읽어볼 것.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;VisualStudio 2019 community 설치(또는 다른 VisualStudio 버전중 택 1)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;git 프로그램을 통해 해당 주소에서 소스 다운로드하고&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;윈도우 도스명령창(cmd.exe) 창에서 &#39;bootstrap-vcpkg.bat&#39; 입력후 &amp;lt;enter&amp;gt; 하면&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span face=&quot;&quot; style=&quot;background-color: #fafbfc; color: #24292e; font-size: 16px;&quot;&gt;vcpkg.exe 가 생생됨.&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;아래와 같이 명령을 사용할 수 있으며&lt;/p&gt;&lt;p&gt;&amp;gt;vcpkg version&amp;nbsp; &amp;nbsp; &amp;lt;- 버젼 확인&lt;/p&gt;&lt;div&gt;&amp;gt;vcpkg list&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;- 설치된 패키지 목록 조회&lt;/div&gt;&lt;p&gt;&amp;gt;vcpkg search &amp;lt;pkgname&amp;gt; &amp;lt;- 설치하고픈 이름의 패키지 찾기&lt;/p&gt;&lt;p&gt;&amp;gt;vcpkg install &amp;lt;pkgname&amp;gt;&amp;nbsp; &amp;lt;- 패키지 설치&lt;/p&gt;&lt;p&gt;&amp;gt;vcpkg remove &amp;lt;pkgname&amp;gt; &amp;lt;- 패키지 삭제&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;ex) mysql 검색시&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;G:\vcpkg&amp;gt;vcpkg search mysql&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;gdal[mysql-libmariadb]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Add mysql support using libmariadb&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libmariadb&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;3.1.7#2&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; MariaDB Connector/C is used to connect C/C++ applications to MariaDB and MySQL...&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libmariadb[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Enable SSL support&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libmariadb[zlib]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Use internal zlib&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libmysql&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;8.0.20&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A MySQL client library for C development.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libodb-mysql&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2.4.0-7&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; MySQL support for the ODB ORM library&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;poco[mysql]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Mysql support for POCO&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;sqlpp11-connector... 0.29-1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A C++ wrapper for MySQL meant to be used in combination with sqlpp11.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;sqlpp11-connector-mysql[mariadb]&amp;nbsp; &amp;nbsp; &amp;nbsp; Use MariaDB connector&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;sqlpp11-connector-mysql[mysql]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Use MySQL connector&lt;/span&gt;&lt;/p&gt;&lt;p&gt;If your library is not listed, please open an issue at and/or consider making a pull request:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; https://github.com/Microsoft/vcpkg/issues&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;ex&amp;gt;openssl 검색시&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;G:\vcpkg&amp;gt;vcpkg search openssl&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;boringssl&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 2020-04-07&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;BoringSSl is a fork of OpenSSL developed by Google&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;boringssl[tools]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Build bssl executable&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;curl[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;SSL support (OpenSSL)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;ffmpeg[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;openssl support in ffmpeg&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;freetds[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; OpenSSL support&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;ixwebsocket[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SSL support (OpenSSL)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libarchive[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;OpenSSL support&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libevent[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Support for openssl&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libevhtp[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Support SSL for libevhtp&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libmariadb[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Enable SSL support&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libpq[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; support for encrypted client connections and random number generation on platf...&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;librdkafka[ssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Build with OpenSSL&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libressl&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2.9.1#3&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; LibreSSL is a version of the TLS/crypto stack forked from OpenSSL in 2014, wit...&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libressl[tools]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Build openssl and ocspcheck executables&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libssh[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Crypto support (OpenSSL)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;libzip[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;AES (encryption) support using OpenSSL&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;mongoose[ssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Build with openssl&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;open62541[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Enable encryption support (uses OpenSSL)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;openssl&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1.1.1g&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;OpenSSL is an open source project that provides a robust, commercial-grade, an...&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;openssl-unix&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1.1.1g#1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;OpenSSL is an open source project that provides a robust, commercial-grade, an...&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;openssl-uwp&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1.1.1g&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;OpenSSL is an open source project that provides a robust, commercial-grade, an...&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;openssl-windows&amp;nbsp; &amp;nbsp; &amp;nbsp; 1.1.1g&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;OpenSSL is an open source project that provides a robust, commercial-grade, an...&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;restbed[openssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Secure over the wire communication allowing you to transmit private data online.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;usockets[ssl]&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Build usockets with openssl support&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;If your library is not listed, please open an issue at and/or consider making a pull request:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; https://github.com/Microsoft/vcpkg/issues&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;gt;내용 추가, x64-windows-static 옵션을 주면, static 빌드도 얻을수 있슴.&lt;/p&gt;&lt;p&gt;아래는 지원하는 형식&lt;/p&gt;&lt;p&gt;G:\vcpkg&amp;gt;vcpkg help triplet&lt;/p&gt;&lt;p&gt;Available architecture triplets&lt;/p&gt;&lt;p&gt;VCPKG built-in triplets:&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm-uwp&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm64-windows&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-linux&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-osx&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-uwp&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-windows-static&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-windows&lt;/p&gt;&lt;p&gt;&amp;nbsp; x86-windows&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;VCPKG community triplets:&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm-ios&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm-mingw-dynamic&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm-mingw-static&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm-windows&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm64-ios&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm64-mingw-dynamic&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm64-mingw-static&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm64-osx&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm64-uwp&lt;/p&gt;&lt;p&gt;&amp;nbsp; arm64-windows-static&lt;/p&gt;&lt;p&gt;&amp;nbsp; s390x-linux&lt;/p&gt;&lt;p&gt;&amp;nbsp; wasm32-emscripten&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-ios&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-mingw-dynamic&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-mingw-static&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-osx-dynamic&lt;/p&gt;&lt;p&gt;&amp;nbsp; x64-windows-static-md&lt;/p&gt;&lt;p&gt;&amp;nbsp; x86-ios&lt;/p&gt;&lt;p&gt;&amp;nbsp; x86-mingw-dynamic&lt;/p&gt;&lt;p&gt;&amp;nbsp; x86-mingw-static&lt;/p&gt;&lt;p&gt;&amp;nbsp; x86-uwp&lt;/p&gt;&lt;p&gt;&amp;nbsp; x86-windows-static-md&lt;/p&gt;&lt;p&gt;&amp;nbsp; x86-windows-static&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;주의 또는 참고&lt;/p&gt;&lt;p&gt;1.패키지는 보통 x86-windows, x64-windows, x64-windows-static 버젼이 있었슴.&lt;/p&gt;&lt;p&gt;&amp;gt;vcpkg install &lt;span style=&quot;font-size: small;&quot;&gt;libmysql:x64-windows&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;입력시 64비트 버전 설치 가능 입력하지 않으면, x86버젼 설치&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&amp;gt;vcpkg remove libmysql:x64-windows&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;삭제시에도 구분해서 삭제를 해주어야 함.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;2.패키지 설치시에 필요한 파일이 vcpkg 아래 폴더에 다운로드 되고, 설치되고,&lt;/p&gt;&lt;p&gt;컴파일이 되어, vcpkg/installed 폴더 아래에 설치 되었슴&lt;/p&gt;&lt;p&gt;vcpkg/ports 는 로컬에 현재 설치가능한 목록을 로컬에 가지고 있어서, 검색을 용이하게&lt;/p&gt;&lt;p&gt;하는 것.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;3.패키지 설치에 Dynamic Library(.dll) 또는 Static Library(.lib) 타입 이미 결정되어 있는 듯&lt;/p&gt;&lt;p&gt;아마도 CMake 툴 기반으로 동작하는 것 같은데, 해당 빌드 속성 변경은 잘모르겠슴.&lt;/p&gt;&lt;p&gt;boost 부터, openssl 까지 왠만한 모듈은 거의 다 있슴.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;4.vcpkg integrate install&lt;/p&gt;&lt;p&gt;-&#39; visualStuio에서 vcpkg에서 설치한 패키지를 사용하고 싶으면 꼭 해줘야 함. (단, 이걸 몇번 해봐야 하는지는 모름.&amp;nbsp; 필요한 것 다 설치하고 한번 해주면 되지 않을까?)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;5. vcpkg 생성이 실패하거나 해당 패키지 설치후 빌드시 실패하면&lt;/p&gt;&lt;p&gt;관련 Issue( https://github.com/Microsoft/vcpkg/issues ) 쪽에서 관련 정보를 찾아보면 동일한 문제가 올라와 있으면, 조만간 수정된 내역이 올라오거나, 수정된 내용을 참고 해서 직접 수정하면 됨.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/4870092884986558447/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2020/08/vcpkg-visualc-package-manager.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/4870092884986558447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/4870092884986558447'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2020/08/vcpkg-visualc-package-manager.html' title='vcpkg - VisualC 용 package manager'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-943546555724054792</id><published>2020-01-12T22:55:00.003-08:00</published><updated>2020-01-12T22:55:42.750-08:00</updated><title type='text'>c++ 현재 시간의 ms 구하는 함수</title><content type='html'>link:&amp;nbsp;&lt;a href=&quot;https://stackoverflow.com/questions/19555121/how-to-get-current-timestamp-in-milliseconds-since-1970-just-the-way-java-gets&quot;&gt;https://stackoverflow.com/questions/19555121/how-to-get-current-timestamp-in-milliseconds-since-1970-just-the-way-java-gets&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
현재 시간의 milisecond 단위 구하는 함수, C++&lt;br /&gt;
&lt;br /&gt;
__int64 llTime = 0;&lt;br /&gt;
std::chrono::milliseconds ms = std::chrono::duration_cast&amp;lt;std::chrono::milliseconds&amp;gt;(&lt;br /&gt;
std::chrono::system_clock::now().time_since_epoch());&lt;br /&gt;
&lt;br /&gt;
llTime =&amp;nbsp;static_cast&amp;lt;long long&amp;gt;(ms.count());&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/943546555724054792/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2020/01/c-ms.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/943546555724054792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/943546555724054792'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2020/01/c-ms.html' title='c++ 현재 시간의 ms 구하는 함수'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-9169376481521573836</id><published>2020-01-08T23:05:00.002-08:00</published><updated>2020-01-08T23:05:28.064-08:00</updated><title type='text'>윈도우 환경변수에 오늘 날짜 구하기</title><content type='html'>Windows /cmd /batch shell/ save to variable&lt;br /&gt;
&lt;br /&gt;
@REM 날짜 프로그램으로 오늘 날짜 추출하여 환경변수에 저장&lt;br /&gt;
FOR /F &quot;TOKENS=1 eol=/ DELIMS=/ &quot; %%A IN (&#39;DATE /T&#39;) DO SET Y4_M2_D2=%%A&lt;br /&gt;
SET Y2M2D2=%Y4_M2_D2:~2,2%%Y4_M2_D2:~5,2%%Y4_M2_D2:~8,2%&lt;br /&gt;
SET TODAY=%Y2M2D2%&lt;br /&gt;
&lt;br /&gt;
@REM 또는 다른 형태로 값을 얻어와서 합치기&lt;br /&gt;
@REM for /f %%x in (&#39;wmic path win32_localtime get /format:list ^| findstr &quot;=&quot;&#39;) do set %%x&lt;br /&gt;
@REM set Y4M2D2_VAR=%Year%%Month%%Day%&lt;br /&gt;
@REM set Y2M2D2_VAR=%Year:~2,2%%Month%%Day%&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/9169376481521573836/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2020/01/blog-post.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/9169376481521573836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/9169376481521573836'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2020/01/blog-post.html' title='윈도우 환경변수에 오늘 날짜 구하기'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-4130353013913175521</id><published>2020-01-08T22:13:00.001-08:00</published><updated>2020-01-08T22:13:05.970-08:00</updated><title type='text'>Bowpad 용 batch script</title><content type='html'>@SET LOG_TODAY=200109&lt;br /&gt;
@REM&lt;br /&gt;
@&quot;C:\Program Files\BowPad\BowPad.exe&quot; /path:&quot;D:\LogIn\SYSLOG\Login_%LOG_TODAY%.log&quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- 이상 -&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/4130353013913175521/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2020/01/bowpad-batch-script.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/4130353013913175521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/4130353013913175521'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2020/01/bowpad-batch-script.html' title='Bowpad 용 batch script'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-162016689345849323</id><published>2019-12-03T17:57:00.000-08:00</published><updated>2019-12-03T17:57:01.831-08:00</updated><title type='text'>Richcopy - Fast Windows Batch copy</title><content type='html'>Link:&lt;br /&gt;
&lt;a href=&quot;https://ksmk.tistory.com/55&quot;&gt;https://ksmk.tistory.com/55&lt;/a&gt;&lt;br /&gt;
http://download.microsoft.com/download/f/d/0/fd05def7-68a1-4f71-8546-25c359cc0842/HoffmanUtilitySpotlight2009_04.exe&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/162016689345849323/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2019/12/richcopy-fast-windows-batch-copy.html#comment-form' title='2개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/162016689345849323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/162016689345849323'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2019/12/richcopy-fast-windows-batch-copy.html' title='Richcopy - Fast Windows Batch copy'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3963934897749362059.post-2919659707648803036</id><published>2019-12-01T22:02:00.001-08:00</published><updated>2019-12-01T22:03:29.283-08:00</updated><title type='text'>BSON - Binary JSON</title><content type='html'>Korean Link&lt;br /&gt;
&lt;div&gt;
&lt;a href=&quot;https://ohgyun.com/421&quot;&gt;https://ohgyun.com/421&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
English Link&lt;br /&gt;
&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;, &amp;quot;Apple SD 산돌고딕 Neo&amp;quot;, NanumGothic, 나눔고딕, ng, sans-serif; font-size: 16px; margin: 0px; padding: 0px;&quot;&gt;
&lt;a class=&quot;tx-link&quot; href=&quot;http://bsonspec.org/&quot; style=&quot;background-color: transparent; box-sizing: border-box; color: #337ab7; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;http://bsonspec.org/&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;, &amp;quot;Apple SD 산돌고딕 Neo&amp;quot;, NanumGothic, 나눔고딕, ng, sans-serif; font-size: 16px; margin: 0px; padding: 0px;&quot;&gt;
&lt;a class=&quot;tx-link&quot; href=&quot;http://en.wikipedia.org/wiki/BSON&quot; style=&quot;background-color: transparent; box-sizing: border-box; color: #337ab7; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/BSON&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://alexnetster.blogspot.com/feeds/2919659707648803036/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://alexnetster.blogspot.com/2019/12/bson-binary-json.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/2919659707648803036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3963934897749362059/posts/default/2919659707648803036'/><link rel='alternate' type='text/html' href='http://alexnetster.blogspot.com/2019/12/bson-binary-json.html' title='BSON - Binary JSON'/><author><name>edgar</name><uri>http://www.blogger.com/profile/13320751958614309707</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>