Jekyll2022-01-09T13:48:53+00:00https://gwonsungjun.github.io/atom.xmlSungjun .DevSoftware Engineer blogSungjunGwon이상한 모임 세미나 - 99CON 참석 후기2019-09-26T00:00:00+00:002019-09-26T00:00:00+00:00https://gwonsungjun.github.io/articles/2019-09/99con-resume<p>99CON 세 번째 이야기 ‘이력서’를 다녀와서</p>
<hr />
<p>어떻게 하면 이력서를 잘 쓸 수 있을까 참석했다가 앞으로의 공부 방향도 정하게 된, 안 갔으면 어쩔뻔했나 싶은 99CON 세 번째 모임 ‘이력서’에 다녀온 후기를 들려드리겠습니다.</p>
<h2 id="1-메인세션">1. 메인세션</h2>
<h3 id="1-7개의-타이틀-7번의-기회-최지호님-스타트업">[1] 7개의 타이틀, 7번의 기회 (최지호님, 스타트업)</h3>
<p>“이력서 없이 이직할 수 있는 커리어 만들기” 주제로 발표</p>
<ul>
<li>전산학과가 아닌 비전공자로써 대학원까지 졸업</li>
<li>L 사 디자인센터 > L사 사내벤처회사 > 네이버 웨일(Product Designer > Product Leader > Product Manager)</li>
</ul>
<h4 id="1-주니어의-면접">1. 주니어의 면접</h4>
<p><strong>이 친구 꼭 뽑아야겠다고 생각한 경우</strong></p>
<ol>
<li>경험의 폭이 좁아도 생각의 폭이 넓은 지원자</li>
<li>무언가를 탐구하고 깊이 파고드는 성향이 보이는 지원자</li>
<li>하지만 사고가 유연하고 상대를 배려할 수 있는 지원자</li>
<li>똑똑한 지원자</li>
<li>호기심이 많은 지원자</li>
</ol>
<p><strong>불합격시킨 경우</strong></p>
<ol>
<li>본인이 한 일을 듣는 사람 입장에서 잘 설명하지 못하는 지원자</li>
<li>본인의 기여도를 부풀리는 지원자</li>
<li>제품의 성격/단계 맞니 않는 성향의 지원자
<ul>
<li>기술 지향의 제품인데 컨텐츠 위주 경력인 경우</li>
<li>초기 기획 단계인데 운영 위주의 경력인 경우</li>
</ul>
</li>
</ol>
<h4 id="2-주니어의-평가">2. 주니어의 평가</h4>
<p><strong>좋은 평가를 주는 경우</strong></p>
<ol>
<li>얼마나 많이, 빠르게 배우려고 노력하는지 - 학습</li>
<li>끝까지 생각해보고 얘기하는지 - 고민의 깊이</li>
<li>빈 곳을 주도적으로 채우는지 - 적극성과 배려</li>
<li>두드러지는 강점 하나가 있는지 - 캐릭터와 매력</li>
<li>글쓰기, 문서화 능력 - 커뮤니케이션</li>
</ol>
<h4 id="3-스타트업으로-이직하다">3. 스타트업으로 이직하다</h4>
<ul>
<li>“이거 내가 만들었어”, “이거 내 거야” 하고 싶었다.</li>
</ul>
<blockquote>
<p>“2.0까지 만들어본 사람이 진정한 기획자다. - 최성호(LG전자 전무)”</p>
</blockquote>
<p><strong>이력서 없이 이직하는 방법</strong></p>
<ul>
<li>나를 증명할 무엇인가를 만드세요.</li>
<li>나의 가치를 인정해줄 수 있는 사람들을 만나세요.</li>
</ul>
<p><strong>그걸 어떻게 하냐고요?</strong></p>
<ol>
<li>레퍼런스를 쌓을 수 있는 일을 많이 하세요. 사람들은 내가 해낸 일을 기억합니다.</li>
<li>이런 행사에 자주 참여해서 시야와 인맥을 넓히세요.</li>
<li>시끄러운 분야에서 일하세요. 본인을 알릴 기회가 많아집니다.</li>
<li>가까운 동료에게 인정받을 수 있게 일하세요. 언젠가 그 사람들이 나의 가치를 증명해줍니다.</li>
</ol>
<h4 id="4-꿀팁">4. 꿀팁</h4>
<ol>
<li>링크드인에 영어로 이력을 자세히 남기세요. 구조화된 이력서를 있어 보이게 만들 수 있습니다.</li>
<li>이력서를 달라는 사람들에게 링크드인 링크를 보내세요.</li>
<li>링크드인 이력서를 pdf로 익스포트 할 수도 있습니다.</li>
</ol>
<h3 id="2-주니어-개발자의-이력서-쓰기-이동욱님-우아한형제들">[2] 주니어 개발자의 이력서 쓰기 (이동욱님, 우아한형제들)</h3>
<ul>
<li>이력서 예시 (샘플로 참고): <a href="https://jojoldu.github.io/">https://jojoldu.github.io/</a></li>
<li>경력: SI 10개월 > zum 2년 > 스타트업(배민) 2년 9개월</li>
<li>이렇게 안 해도 네이버 카카오 가던데요?
<ul>
<li>이 발표의 지향점 > 조금만 더 첨가하면 좋으실 분들</li>
</ul>
</li>
</ul>
<h4 id="워밍업">워밍업</h4>
<ul>
<li>프로젝트는 역순 정렬 (DESC), 주문 내역처럼 역순 정렬이 기본이다.
<ul>
<li>경력 포함 모든 이력들도 마찬가지</li>
</ul>
</li>
<li>이력서 제출은 PDF (한글, 워드 x)
<ul>
<li>채용사이트 브라우저에서 즉시 볼 수 있는 형태가 가장 좋다.</li>
</ul>
</li>
<li>절대 압축 하지 마세요.</li>
</ul>
<h4 id="보편적인-이력서-양식">보편적인 이력서 양식</h4>
<ul>
<li>필수
<ul>
<li>본인 프로필 (이름, GitHub 주소, 블로그 주소 등)</li>
<li>본인 소개
<ul>
<li>5~7 줄로 어떤 개발자인지</li>
</ul>
</li>
<li>기술 스택</li>
<li>오픈소스 / 프로젝트 / 경력 (순서는 무관)</li>
</ul>
</li>
<li>선택
<ul>
<li>교육 / 발표 / 집필</li>
<li>기타 등등</li>
</ul>
</li>
</ul>
<h4 id="1-본인-프로필">1. 본인 프로필</h4>
<ul>
<li>이름, 이메일, 깃허브 -<code class="language-plaintext highlighter-rouge">필수</code></li>
<li>블로그 - <code class="language-plaintext highlighter-rouge">준 필수</code></li>
<li>사이드 프로젝트 있으면 <code class="language-plaintext highlighter-rouge">가산점 ++</code></li>
<li>링크드인, 페이스북 등 SNS 계정 - 선택</li>
</ul>
<p><strong>Question.</strong></p>
<ul>
<li>Github이 깡통이라면 ? TIL (o), fork (효과 x, fork로 잔디밭 만들지 마!), 학교 프로젝트 (효과 o)</li>
<li>블로그가 없는데요? 웬만하면 만드세요. (네이버 블로그 제외…)</li>
</ul>
<p>하고 싶은 말</p>
<ul>
<li>서류 외에도 볼 게 많은 사람을 선호</li>
<li><code class="language-plaintext highlighter-rouge">좋은 사람을 놓치는 것보다 안 좋은 사람을 뽑는 걸 더 두려워한다. (잘못된 사람을 뽑으면 팀 하나가 망가진다.)</code></li>
<li><code class="language-plaintext highlighter-rouge">서류 심사관이 도박을 하도록 만들지 마세요. (오늘 발표에서 가장 전달하고 싶은 말)</code></li>
</ul>
<h4 id="2-본인-소개">2. 본인 소개</h4>
<ul>
<li>일종의 summary</li>
<li>어떤 경험을 해왔는지, 어떤 생각을 갖고 있는지, 평소에 어떤 노력을 하고 있는지 등등
<ul>
<li>예시) 자동화, 테스트코드, 팀에 도움 등…</li>
</ul>
</li>
<li>최대한 숫자로 표현
<ul>
<li>대용량/대규모 → RPM/TPS/PV/MAU 등 구체적 숫자</li>
</ul>
</li>
</ul>
<p><strong>Question.</strong></p>
<ul>
<li>피해야 할 단어 ?
<ul>
<li>열정/노력/도전 정신 등 (이거 없는 분 계시나요)</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">증명할 수 있는</code> 단어들을 선택하자.
<ul>
<li>숫자로 기록 (커밋, 세미나 좋아한다 세미나 후기 등)</li>
<li>볼 수도 없는데 교육, 세미나 다니는데 어떻게 증명? 증거가 있어야 한다.</li>
</ul>
</li>
</ul>
<h4 id="3-기술-스택">3. 기술 스택</h4>
<ul>
<li>1~2번 써본 기술은 언급하지 않는다.</li>
<li>주력 기술들만 언급하자.</li>
<li>경력에 비해 너무 많은 기술 스택은 오히려 좋지 않다.</li>
<li>Java 백엔드 개발자 직군에 지원하면서 머신러닝/블록체인/AI 등등은 소용 없다. (주니어가 위 기술이 주력으로 하기엔 어렵다)</li>
</ul>
<p><strong>Question.</strong></p>
<ul>
<li>그동안 해온 기술과 다르다면? 러닝커브를 강조하는 이력서로</li>
<li>내가 얼마나 빠르게/바르게 기술을 배울 수 있는 사람인지 (나만의 학습 방법을 이야기해 주세요.)</li>
</ul>
<h4 id="4-경력프로젝트">4. 경력/프로젝트</h4>
<p>프로젝트</p>
<ul>
<li>질문하면 답변할 수 있는 프로젝트만</li>
<li>맡은 개발 파트 요약</li>
<li>프로젝트에서 특히 강조하고 싶은 것</li>
<li>성과/실적도 있다면 추가</li>
<li>가능하면 증명 가능한 링크</li>
</ul>
<p>경력</p>
<ul>
<li>근무 기간</li>
<li>프로젝트가 있으니 요약정리한다.</li>
<li>프로젝트 성과 외 언급할 것들</li>
</ul>
<p><strong>Question.</strong></p>
<ul>
<li>경력/프로젝트가 너무 적을 때는?
<ul>
<li>교육/스터디로 간을 맞추자.</li>
</ul>
</li>
</ul>
<h4 id="4-1-교육-스터디">4-1. 교육 스터디</h4>
<p>어떤 기준으로 교육을 선택하고 무엇을 배웠는지 정리한다. (증거는 필수)</p>
<p><strong>Question.</strong></p>
<ul>
<li>교육 / 스터디 주제는? <code class="language-plaintext highlighter-rouge">테스트 코드 / OOP / 클린 코드, 쿼리 튜닝, 리눅스 등... (백엔드 개발자 기준)</code>
<ul>
<li><code class="language-plaintext highlighter-rouge">혼자서 MSA(,쿠버네티스) 연습 중이라는 말은 하지 말자, 테스트 코드 oop 등이 먼저다.</code></li>
<li><code class="language-plaintext highlighter-rouge">주니어 개발자들에게 기대하는 건 탄탄한 기본기</code></li>
</ul>
</li>
<li>최근 코딩테스트: 알고리즘 테스트 → 과제 중심 (2주를 주고 제품을 만들어라 대신 테스트 코드 필수)</li>
</ul>
<h4 id="5-오픈소스">5. 오픈소스</h4>
<p><strong>Question.</strong></p>
<ul>
<li>star 많은 오픈소스는 효과가 있다? 필수?
<ul>
<li><a href="http://rankedin.kr">rankedin.kr</a> 기준 국내 오픈소스 랭킹 42위 but 이력서에 사용되는 일은 없었다.</li>
</ul>
</li>
<li>코드가 없는 저장소는 효과가 없다. (아예 저장소가 없는 것보다는 낫습니다.)</li>
<li>star가 적어도 <code class="language-plaintext highlighter-rouge">코드가 있는 저장소가 효과가 있다.</code>
<ul>
<li>springboot-aws-mock (jojoldu repo) 이 부분에 대해서 질문을 더 많이 받음</li>
</ul>
</li>
</ul>
<h4 id="6-포트폴리오">6. 포트폴리오</h4>
<ul>
<li>작품의 호응도와 개발 실력을 동일시해서 말하면 안 됨</li>
<li>졸업작품 전시회 하듯이 포트폴리오 하면 효과가 없다.(기능, ui, 기획 등등이 강조된 PPT)
<ul>
<li><code class="language-plaintext highlighter-rouge">서류 검토자는 코드가 보고 싶다.</code>
<ul>
<li><code class="language-plaintext highlighter-rouge">테스크 코드를 작성하는지, 객체지향적으로 작성하는지, 커밋메시지 등등</code></li>
</ul>
</li>
</ul>
</li>
<li>보안 문제가 없다면 포트폴리오 프로젝트는 모두 깃헙에 올린다.
<ul>
<li>REAME.md에 작품 소개와 실행 방법을 작성한다.</li>
<li>잘 작성된 commit도 있다면 가산점 ++</li>
</ul>
</li>
</ul>
<h4 id="7-꿀팁">7. 꿀팁</h4>
<ul>
<li>문제 해결 사례 언급하기
<ul>
<li>학교 프로젝트, 국비 교육, 스터디 등 하면서 만났던 문제를 해결한 사례
<ul>
<li>어떻게 해결했는지를 보면 참고가 많이 된다.</li>
<li>블로그에 정리하듯이 정리해서 이력서 summary에 언급</li>
<li>사례 2가지 정도가 있으면 많이 도움 된다.</li>
<li><a href="https://jojoldu.tistory.com/40">https://jojoldu.tistory.com/40</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="마무리">마무리</h4>
<ul>
<li>강원국의 글쓰기: 잘 쓰려면 잘 살아야 한다.
<ul>
<li>이력서 잘 쓰려면 좋은 개발자로 잘 살아야 한다</li>
<li><code class="language-plaintext highlighter-rouge">좋은 개발자가 되기 위한 노력이 우선이지 좋은 이력서가 우선 되선 안된다.</code></li>
</ul>
</li>
</ul>
<h3 id="패널-토크강미경님-최지호님-이동욱님">패널 토크(강미경님, 최지호님, 이동욱님)</h3>
<p><strong>Q. 다양한 것들 중에 어떤 걸 남기고, 어떤 걸 빼야 하는지가 어렵습니다.</strong></p>
<ul>
<li>A. 이상한모임 강미경님 적은 글 확인 (<a href="https://blog.weirdx.io/post/61288">https://blog.weirdx.io/post/61288</a>)</li>
</ul>
<p><strong>Q. 대외활동이나 외국어 능력 등을 어떻게 작성하는게 좋을까요? 서류통과나 면접에서 많이 중요한가요?</strong></p>
<ul>
<li>A. 스토리가 중요. 개발 경험 산만하게 쭉 나열한건 의미 없음, 하나로 엮여서 스토리를 만들고, 이런 능력이 있으니깐 이런걸 기여할 수 있다 어필하면 좋음</li>
</ul>
<p><strong>Q. 비전공자로 개발을 하고 있습니다. 전공지식이 없는 것을 어떻게 보완해야 할지 막막합니다.</strong></p>
<ul>
<li>A. 전공지식이 부족한 부분은 돈으로 교육을 듣는다. (자바지기님 등의 교육) 유료기관, 돈을 투자해서라도 듣는거 추천</li>
</ul>
<p><strong>Q. 주니어때 했던 일 기억나지 않고 신입 때 했던 것들은 기술에 대한 변별력이 없었는데 어떻게 기술해야 할까요?</strong></p>
<ul>
<li>A. 버려라~</li>
</ul>
<p><strong>Q. 이력서도 자기 PR, 흥미롭고 쉬운 이력서를 만들 것인지? 이해해야 하지만 철저하고 꼼꼼한 서류를 만들어야 할지 고민입니다.</strong></p>
<ul>
<li>A. 흥미롭고 쉬운 게 중요하다. 면접을 무조건 가야 하는데, 이력서에서 매력적이고 재밌고 흥미가 있어서 이 사람 만나서 이런거 물어보고 싶다는 생각이 들어야 한다.</li>
</ul>
<p><strong>Q. 이력서와 경력기술서를 분리해서 관리하는 것이 맞으까요? 내용이 중복으로 보이는건 아닐까요?</strong></p>
<ul>
<li>A. 경력기술서 따로 안 씀</li>
</ul>
<p><strong>Q. 운영 위주로 업무를 진행하는데, 경력 기술서 어떻게 작성해야 할까요?</strong></p>
<ul>
<li>A. 어떤 프로젝트를 개선하려고 노력했는지에 대한 설명</li>
</ul>
<p><strong>Q. 지원동기를 어떻게 써야 할지 감이 오지 않습니다. 그 회사만을 위한 맞춤 지원동기를 작성하는 팁이 있을까요?</strong></p>
<ul>
<li>A. 하고 싶은 일이 있어야 가는 거지, 여기가 싫어서 가면 후회할 것이다. 하고 싶은 일이 명확히 드러나고 이 프로덕트에 얼마나 관심이 많은지 들어내면 좋음 (없으면 정성이 안 느껴진다.)</li>
</ul>
<p><strong>Q. 회사 업무만으로는 지원하는 직무에 부족하다고 느낄 때, 사이드 프로젝트로 어필해도 좋을까요?</strong></p>
<ul>
<li>A. 사이드 프로젝트가 코드로만 끝나지 않고 웹이나 앱으로 도메인까지 붙어있으면 좋다. (남는 시간에 부족한 걸 채우기 위해 공부했다. → 큰 가산점) , 지금 하는 직무와 맞지 않으면 사이드 프로젝트 GOGO
<ul>
<li>회사 업무는 js 프론트 개발 주력, 사이드 프로젝트로 백엔드 프로젝트 해서 어필하니 효과가 있었다.</li>
</ul>
</li>
</ul>
<p><strong>Q. 백엔드 개발을 하다 프론트로 전직함, 다시 프론트 개발자로 이원할때, 이전 백엔드 경력도 써야하나? 앱도 공부한적 있는데 도움이 될까?</strong></p>
<ul>
<li>A. 하나의 서비스를 만드는데 필요한 기술이기 때문에 도움이 된다. 프론트엔드 개발을 하고 있지만 백엔드 해봤기 떄문에 api 통신, json spec 맞추는 커뮤니케이션에 친숙하다.</li>
</ul>
<p><strong>Q. 다른 직무로 전직, 목표하는 직무에 대한 업무 경험이 없는데 어떻게 보완?</strong></p>
<ul>
<li>A. 교육 등으로, 돈을 바르는 방법도 있음.</li>
</ul>
<p><strong>Q. 저와 맞는 회사인지 어떻게 알 수 있나요?</strong></p>
<ul>
<li>A. 나랑 맞는 조건이 어떤 건지 나열해 보자. 내 성향은 어떻고 나랑 맞는 회사는 어떤 회사인지 생각하고 정리하자
<ul>
<li>내 성향 파악 (내향, 외향)</li>
<li>돈보다 성장의 기회를 잡자?</li>
</ul>
</li>
</ul>
<p><strong>Q. 지금 프로젝트를 진행하고 있는데, 중간에 퇴사하면 민폐가 되지 않나요?</strong></p>
<ul>
<li>A. 그걸 걱정할건 매니저가 할 일. 빨리 얘기해서 매니저가 해결책을 찾도록 해야함, 민폐가 아닐까라는 생각을 굳이 안 해도 될 것 같다.</li>
</ul>
<p><strong>Q. 지금 회사가 하고 싶은 분야가 아니라서, 정말 하고 싶은 분야로 이직할 때 경력으로 인정해줄까 고민입니다.</strong></p>
<ul>
<li>A. 경력으로 인정을 해주면서 그만큼의 퍼포먼스에 대한 기대를 못 채울 것 같다면 경력으로 인정해주지 않는 것이 다행일 수 있다. 연봉에 대한 부분은 입사해서 퍼포먼스를 내면 연봉협상을 할 수 있으니까..</li>
</ul>
<p><strong>Q. 개발실력 이외에 개발자가 신경 쓰고 발전시켜야 하는 역량이 있다면 무엇이 있을까요?</strong></p>
<ul>
<li>A. <code class="language-plaintext highlighter-rouge">나보다 경력 높은 사람을 설득할 수 있어야 하고, 경력 낮은 사람한테 설득당할 수 있어야 한다.</code> 협업하는 능력을 키우는게 좋다.</li>
</ul>
<p><strong>Q. 커리어의 방향과 계획을 세우는게 막연합니다. 구체화하고 실천할 수 있는 방법이 무엇이 있을까요?</strong></p>
<ul>
<li>A. 큰 회사에서 점점 작은 회사로 가면서 부품이 아닌 내 것을 만들어보자. 즉, 방향은 있었지만 따로 구체적인 계획은 없었다.</li>
</ul>
<h2 id="2-라이트닝-토크">2. 라이트닝 토크</h2>
<h3 id="1415-미래를-준비하는-자세-신예진님-에멘탈">14:15 미래를 준비하는 자세 (신예진님, 에멘탈)</h3>
<ul>
<li>경영 지원: 텍스트 위주의 이력서 (No Portfolio) > 서비스 기획자로 전직</li>
<li>서비스 기획자로서 이력서에 대한 고민
<ul>
<li>서비스 기획자란 커리어를 계속 이어갈 수 있을까?</li>
<li>커리어를 이어간다면 어떻게 내 실력을 증명해야 할까</li>
<li>포트폴리오는 만들어 본 적이 없는데..?</li>
</ul>
</li>
<li>포티폴리오를 내 방식대로 만들어보자
<ul>
<li>텍스트가 익숙한 장점을 발휘해보자 > 블로그, 브런치 등 기재</li>
<li>토이 플젝을 진행해보자 > 이제 시작, 결과는 아직 모름, 머리 속만 꽃밭</li>
</ul>
</li>
</ul>
<p>왜 이렇게 하죠?</p>
<ul>
<li>인사담당자였던 경험으로 비추어 보아
<ul>
<li>일정 목표를 가지고 미래를 준비한 내용이 이력서에 보이면 +a</li>
<li>그걸 실무에서 쓸 수 있다는게 증명되면 ++aa</li>
</ul>
</li>
</ul>
<h4 id="추가-꿀팁---임원-입장에서-a-점수-주고-싶은-이력서">추가 꿀팁 - 임원 입장에서 +a 점수 주고 싶은 이력서</h4>
<ul>
<li>이력서의 핵심과 상세를 나누기
<ul>
<li>꼭 전달하고 싶은 핵심 되는 요소를 상단에 짧고 집중력 있게</li>
<li>채용담당자는 모든 이력서를 집중력 있게 읽지 않는다</li>
<li>정리된 상세 영역은 또 하나의 포트폴리오</li>
</ul>
</li>
<li>이전 회사 포트폴리오를 넣는다면 보안에 신경 쓰기
<ul>
<li>기업 보안은 생각보다 중요한 요소</li>
<li>전에 회사를 먼저 비판하는건 자제</li>
</ul>
</li>
<li>지원하는 회사에 관련된 맞춤형 내용을 넣기
<ul>
<li>이력서는 템플릿처럼 배포가 가능하지만, 이 영역은 우리 회사만을 위한 영역</li>
<li>동일한 관심사라서 채용 담당자의 이목을 집중시키기 좋아요</li>
</ul>
</li>
</ul>
<h3 id="1445-si-탈출기황건구님-마켓컬리">14:45 SI 탈출기(황건구님, 마켓컬리)</h3>
<ul>
<li>si : 결과에 포커스, 서비스: 성장에 포커스</li>
<li>si 1년 차: 사수 없음, 레거시, 저임금, gubun(DB 컬럼명, 다들 아시죠..?), 상사의 거짓말</li>
<li>si 생활 7년차
<ul>
<li>과정을 고민 안하고 결과에 포커싱을 하고 있는 문제</li>
<li>수직적인 구조를 혼자서 깨는건 힘듬</li>
</ul>
</li>
<li>외부 자극 > “그게 개발자로서 무슨 의미가 있는데요?” (si, 레거시, …)
<ul>
<li>시간이 지나면 정말 못하겠구나</li>
</ul>
</li>
<li>차이 메꾸기
<ul>
<li>노력한 흔적: 블로그, 스택오버플로우, 페이스북 친구(컨퍼런스 등 쫓아가서 페북친구 걸고 귀동냥 등등), 오픈소스 기여</li>
<li>수단과 방법을 가리지 않음</li>
</ul>
</li>
<li>능력치 분배는 나의 몫
<ul>
<li>어떤 일이 주어지든 어떤 일을 하든, 내 캐릭터에 스텟을 찍는 건 나다!</li>
</ul>
</li>
<li>회사에 도커, spring boot, ci / cd, vue.js 등을 들고 와서 적용시키고 협업 툴 등을 모두 가이드 함.</li>
<li>탈출할 때는 위의 도커 스프링부트 등을 적용했던걸 얘기</li>
</ul>
<h4 id="마무리-1">마무리</h4>
<ul>
<li>하고싶은거 꾸준히</li>
<li>다른 사람들을 만나보세요</li>
<li>서두르지마세요 월급나오잖아요</li>
<li>주변에 이력서 피드백 꼭 받자</li>
<li>자취중이라면 퇴사 전에 3개월치 생활비 비축</li>
<li>계약서 싸인 전 까진 동료에게 말하지 말기</li>
</ul>
<p>김슬기님의 “이렇게 고쳐보자! 개발자 이력서 작성 Tip”과 “구자경님의 눈떠보니 PM” 라이트닝토크는 들으며 기록을 못 했습니다. <a href="https://medium.com/@byungkyu_ju/세미나참석기-이상한모임-제3회-99콘-이력서-2019-09-21-857ef6cde3fa">다른 분의 세미나 참석 후기</a>를 참고해주세요.</p>
<h2 id="후기">후기</h2>
<ul>
<li>제가 서두에 말했던 공부 방향을 잡게 되었다고 말한 이유는 동욱님의 발표에 있었습니다.
<blockquote>
<p>“혼자서 MSA,쿠버네티스 연습중이라는 말은 하지말자, 테스트 코드 oop 등이 먼저다. 주니어 개발자들에게 기대하는건 탄탄한 기본기”</p>
</blockquote>
</li>
<li>한동안 쿠버네티스, MSA를 공부해야 하나 고민을 많이 하고 공부 플랜에 넣어놨었는데, 과감히 삭제했습니다.</li>
<li>기본기, 어떻게 하면 객체지향적으로 클린하게 코드를 작성할 것인지에 어떻게 하면 테스트 코드를 조금 더 잘 작성할 수 있을지에 집중하려고 합니다.</li>
<li>인사이트를 제공해주신 모든 발표자분들께 감사드립니다.</li>
</ul>sungjun99CON 세 번째 이야기 ‘이력서’를 다녀와서MongoDB, ALERT: Query Targeting: Scanned Objects / Returned has gone above 1000 해결2019-09-24T00:00:00+00:002019-09-24T00:00:00+00:00https://gwonsungjun.github.io/articles/2019-09/mongodb_alert<p>MongoDb Scanned Objects ALERT을 해결해보자</p>
<hr />
<p>4월 이후에 정말 오랜만에 블로깅을 한다. <br />
그동안 많은 변화가 있어서 적응하느라 블로깅을 못 했는데(변명이지만…) 이제 좀 적응되어 그동안 쌓아왔던 이슈들을 하나씩 풀어보려 한다.</p>
<p>현재 MongoDB 클라우드 매니지드 서비스인 Atlas를 Production 환경에서 사용 중이다.</p>
<p>몽고디비를 접한 시기도 얼마 되지 않았고 실제 프로덕션 환경에서의 운영을 처음 해보기 때문에 간단한 Alrert이 mail로 오면 꽤 당황하곤 한다. 익숙함의 문제보다 아직 모르는 게 많아서 그런 거 같다.</p>
<p>이번 포스팅에서 소개할 이슈는 아래와 같다.</p>
<p><code class="language-plaintext highlighter-rouge">ALERT : Query Targeting: Scanned Objects / Returned has gone above 1000</code></p>
<p>먼저 <code class="language-plaintext highlighter-rouge">Scanned Objects</code>이 무엇을 의미하는지부터 찾아보았다.</p>
<p>Atlas Document에 자세히 나와 있지만 간단하게 설명하면 Query Targeting Metric은 2개의 information을 보여주고 있다.</p>
<ul>
<li>scanned / returned: 실제 리턴 된 문서 수와 비교하여 쿼리를 수행하기 위해 검사 된 인덱스 키 수 간의 비율로 사용자 정의 임계 값을 초과하거나 초과하는 경우 발생
<ul>
<li>기본적으로 활성화되어 있지 않음</li>
</ul>
</li>
<li>Scanned Objects / Returned: 반환된 실제 문서 수와 비교하여 쿼리를 수행하기 위해 검사한 문서 수간의 비율로 사용자 정의 임계 값을 초과하거나 초과하는 경우 발생
<ul>
<li>기본 임계 값은 1000. 즉, 쿼리 하나에 1000개 이상의 문서를 스캔한 경우 경고를 알림</li>
</ul>
</li>
</ul>
<p>무슨 말이지? 고민하며 경고 메일 본문을 다시 읽어보는데 힌트가 눈에 들어왔다.</p>
<p><code class="language-plaintext highlighter-rouge">which typically suggests that un-indexed queries are being run</code>: index가 안 걸려 있구나.</p>
<p>근데 해당 mail이 전송되고 <code class="language-plaintext highlighter-rouge">Scanned Objects</code> value가 다시 1000 이하로 내려가면 해당 이슈가 자동적으로 close 되면서 어떤 collections에서 문제가 발생 중인지 확인하기가 어려웠다.</p>
<p>다행히 최근 들어 많이 사용되는 collection이 있었는데 인덱스가 걸려있지 않은 것을 확인하였고 mongoose로 schema를 생성해 사용 중이었기 때문에 <code class="language-plaintext highlighter-rouge">indxe:true</code> 옵션을 추가 및 배포하여 해결하였다.</p>
<p>소스 단에서 mongoose 등을 이용해 스키마를 생성하지 않았다면 직접 shell 또는 gui (mogodb compass)에 접속하여 index를 생성하면 해결될 것이다.</p>
<p>문제 해결 후 Qury Targeting Metric을 확인해보면 문제가 되는 지점에서는 1k까지 치솟았었는데 index 설정 후 확 떨어지는 것을 확인할 수 있다.</p>
<p><img src="/assets/images/usingimages/atlas-query-targeting-metric.png" alt="atlas-query-targeting-metric" /></p>
<p>참고로 index 설정 시 주의할 점</p>
<ul>
<li>모든 도큐먼트를 스캔해야 되는 비효율성을 줄여 주지만 write 및 update operation을 성능을 떨어뜨리므로 읽기 위주인 경우에만 유용</li>
</ul>
<h3 id="link">Link</h3>
<ul>
<li><a href="https://docs.atlas.mongodb.com/reference/alert-resolutions/query-targeting/">https://docs.atlas.mongodb.com/reference/alert-resolutions/query-targeting/</a></li>
</ul>sungjunMongoDb Scanned Objects ALERT을 해결해보자5) Jenkins Tutorial - Registering Jenkins items using pipeline2019-04-18T00:00:00+00:002019-04-18T00:00:00+00:00https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_5<p>Jenkins pipeline을 이용해 아이템 등록 하기</p>
<hr />
<p>이번 시간에는 Jenkins Web UI가 아닌 Jenkins pipeline을 이용해서 item을 등록해보도록 하겠습니다. <br />
전체적인 흐름은 저번 시간과 같습니다. 참고해주시기 바랍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_flow.png" alt="jenkins_flow" /></p>
<h2 id="contents">Contents</h2>
<ol>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_1">Installing Jenkins and GitLab with Docker</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_2">Jenkins, GitLab initial setting</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_3">Create AWS EC2 Instance</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_4">Registering Jenkins items using web ui</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_5">Registering Jenkins items using pipeline</a></li>
</ol>
<h2 id="5-registering-jenkins-items-using-pipeline">5. Registering Jenkins items using pipeline</h2>
<h3 id="5-1-ssh-agent-plugin-설치">5-1. SSH Agent Plugin 설치</h3>
<p>Jenkins 관리 > 플러그인 관리로 이동해서 아래와 같이 <code class="language-plaintext highlighter-rouge">SSH Agent</code> 플러그인을 설치합니다.</p>
<ul>
<li>‘지금 다운로드하고 재시작 후 설치하기’ > ‘설치가 끝나고 실행 중인 작업이 없으면 Jenkins 재시작’ 버튼 체크</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_ssh_agent.png" alt="jenkins_ssh_agent" /></p>
<h3 id="5-2-새로운-item-등록">5-2. 새로운 Item 등록</h3>
<p>Jenkins > 새로운 Item을 클릭하고 아래와 같이 <code class="language-plaintext highlighter-rouge">item 이름</code> 지정, <code class="language-plaintext highlighter-rouge">Pipeline</code>를 선택한 뒤 <code class="language-plaintext highlighter-rouge">OK</code> 버튼을 누릅니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_new_item_pipeline.png" alt="jenkins_new_item_pipeline" /></p>
<h3 id="5-3-pipeline-설정">5-3. Pipeline 설정</h3>
<p>item 설정 화면 맨 밑 <code class="language-plaintext highlighter-rouge">Pipeline</code> 부분부터 설정해보겠습니다.</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">Definition</code> : Pipeline script from SCM 선택</li>
<li><code class="language-plaintext highlighter-rouge">SCM</code> : Git 선택</li>
<li><code class="language-plaintext highlighter-rouge">Repository URL</code> : GitLab project http URL을 입력합니다.
<ul>
<li>현재는 gitlab URL을 docker private ip로 등록해야 합니다. (이전 편에서 말씀드린 것 처럼 실제 상용에서는 이렇게 사용하시면 안됩니다!)</li>
<li>gitlab.example.com 부분을 <code class="language-plaintext highlighter-rouge">docker inspect gitlab | grep "IPAddress"</code> 명령을 통해 나오는 IP로 바꿔줍니다.</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">Credentials</code>
<ul>
<li>혹시 <a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_4">4. Registering Jenkins items using web ui</a>에서 등록하신분들은 이전에 등록한 Credentials를 선택해줍니다.</li>
<li>등록 안하신 분들은 아래의 순서로 등록해줍니다.
<ul>
<li>(1) Add 버튼 클릭 > jenkins 선택</li>
<li>(2) Credentials 생성
<ul>
<li>Domain : Global credentials</li>
<li>Kind : Username with password</li>
<li>Scope : Global</li>
<li>Username : gitlab id</li>
<li>password : gitlab password</li>
<li>ID : 젠킨스 내 식별 ID</li>
<li>Description : Credentials 부연 설명</li>
</ul>
</li>
<li>(3) 생성한 Credentials 선택 > Error 없어지는 것을 확인합니다.</li>
</ul>
</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">Branch Specifier (blank for 'any')</code> : <code class="language-plaintext highlighter-rouge">*/**</code> 입력 (모든 브랜치로부터 event를 받게됩니다.)</li>
<li><code class="language-plaintext highlighter-rouge">Repository browser</code> : 자동</li>
<li><code class="language-plaintext highlighter-rouge">Script Path</code> : <code class="language-plaintext highlighter-rouge">Jenkinsfile.groovy</code> 입력 <code class="language-plaintext highlighter-rouge">(.groovy를 입력해주셔야 합니다!)</code></li>
<li><code class="language-plaintext highlighter-rouge">Lightweight checkout</code> : 체크 해제</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_pipeline_setting.png" alt="jenkins_pipeline_setting" /></p>
<h3 id="5-4-general-설정">5-4. General 설정</h3>
<p>General에는 해당 item을 간단하게 설명해줍니다. <br />
그리고 <code class="language-plaintext highlighter-rouge">이 빌드는 매개변수가 있습니다</code>를 체크해줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_pipeline_general.png" alt="jenkins_pipeline_general" /></p>
<h3 id="5-5-매개변수-추가">5-5. 매개변수 추가</h3>
<p><code class="language-plaintext highlighter-rouge">매개변수 추가</code> 버튼을 눌러 아래와 같이 3개의 <code class="language-plaintext highlighter-rouge">String Parameter</code>를 추가해줍니다. <br />
프로젝트별 상이한 정보들을 매개변수로 추출해서 등록하는 과정입니다.</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">GIT_URL</code> : 깃 저장소 주소
<ul>
<li>위 5-3에서 등록했던 git 주소를 똑같이 입력합니다.</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">CREDENTIALIS_ID</code> : 바로 위 Username with password로 등록한 credentials의 <code class="language-plaintext highlighter-rouge">ID</code>를 입력합니다.</li>
<li><code class="language-plaintext highlighter-rouge">SLACK_CHANNEL</code> : 슬랙 채널명을 입력합니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_pipeline_parameter.png" alt="jenkins_pipeline_parameter" /></p>
<h3 id="5-6-build-triggers-설정">5-6. Build Triggers 설정</h3>
<p>빌드 유발은 <code class="language-plaintext highlighter-rouge">Build when a change is pushed to GitLab</code> 을 선택해줍니다. <br />
그리고 고급 버튼을 눌러 Secret token의 <code class="language-plaintext highlighter-rouge">Generate 버튼</code>을 클릭합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_build_trigger.png" alt="jenkins_build_trigger" /></p>
<p>잠깐 GitLab에 접속해서 <code class="language-plaintext highlighter-rouge">Admin area > settings > network > Outbound requests</code>로 이동하여 <code class="language-plaintext highlighter-rouge">Allow request to the local network from hooks and services</code>를 체크해준 뒤 저장합니다.</p>
<ul>
<li>이 설정을 해주지 않으면 아래 Integrations 설정 시 “Requests to the local network are not allowed” 에러가 발생합니다. (로컬 테스트 시만 체크하시고 상용환경에서는 생략하시고 넘어가면 됩니다.)</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_outbound.png" alt="gitlab_outbound" /></p>
<p>다음, Gitlab 해당 Project > settings > Integrations로 이동하겠습니다. <br />
그리고 URL은 위에서 체크했던 <code class="language-plaintext highlighter-rouge">Build when a change is pushed to GitLab. GitLab webhook URL:</code> 부분의 url 부분만 복사해서 넣습니다.</p>
<ul>
<li>url에서 localhost 부분은 <code class="language-plaintext highlighter-rouge">docker inspect jenkins | grep "IPAddress"</code>를 입력해서 나오는 IP로 바꿔줍니다.
secret token 역시 젠킨스에서 생성한 token을 입력합니다. <br />
적절한 Trigger를 선택해주면 되는데 현재는 Push events만 선택하겠습니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_integrations.png" alt="gitlab_integrations" /></p>
<p>여기까지가 item 등록 끝이고 이대로 저장을 하시면 pipeline item 등록이 완료됩니다.</p>
<h3 id="5-7-jenkinsfilegroovy-파일-생성">5-7. Jenkinsfile.groovy 파일 생성</h3>
<p>먼저 아래와 같이 demo 프로젝트 루트에 Jenkinsfile.groovy 파일을 생성해줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/intellij_jenkinsfile.png" alt="intellij_jenkinsfile" /></p>
<h3 id="5-8--젠킨스-파이프라인-문법">5-8. (+) 젠킨스 파이프라인 문법</h3>
<ul>
<li>젠킨스 파이프라인의 경우 2가지 문법을 지원합니다.
<ul>
<li>Scripted : Groovy 문법을 사용하고 Declarative 문법보다 더 유연하게 사용 가능.</li>
<li>Declarative : 간단하지만 고정된 방식.</li>
</ul>
</li>
<li>저희는 Scripted 문법을 사용해서 Jenkinsfile을 작성할 것입니다. 따라서, Groovy SDK를 설치하고 intellij에 설정하는 것을 권합니다.</li>
<li>파이프라인 문법에 대해 조금 더 상세한 내용은 <a href="https://jojoldu.tistory.com/356?category=777282">젠킨스 파이프라인 정리 - 2. Scripted 문법 소개</a>를 참조해주시기 바랍니다.</li>
</ul>
<p>MacOS 기준 groovy sdk 설치 및 intellij 설정법입니다.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>brew <span class="nb">install </span>groovysdk
<span class="nv">$ </span><span class="nb">export </span><span class="nv">GROOVY_HOME</span><span class="o">=</span>/usr/local/opt/groovy/libexec
Point IntelliJ to the installed directory, e.g.:/usr/local/Cellar/groovysdk/2.4.7/libexec
</code></pre></div></div>
<h3 id="5-9-ssh-agent-설정">5-9. SSH Agent 설정</h3>
<p>Remote Server SSH Private key를 등록합니다. <br />
먼저, 이전에 생성해둔 AWS EC2 Instance 키페어가 저장된 위치로 이동합니다.
아래와 같이 cat 명령을 통해 pem file을 출력하고 출력된 문자열을 복사합니다.</p>
<ul>
<li>복사하실 때는 —–BEGIN RSA PRIVATE KEY—–부터 —–END RSA PRIVATE KEY—–까지 모두 복사해야 합니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/cat_pem.png" alt="cat_pem" /></p>
<p>왼쪽 메뉴에서 Credentials > System > Global credentials > Add Credentials를 클릭해서 복사한 pem file을 등록해줍니다.</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">Kind</code> : SSH Username with private key</li>
<li><code class="language-plaintext highlighter-rouge">Scope</code> : Global</li>
<li><code class="language-plaintext highlighter-rouge">ID</code> : 젠킨스 내 식별 ID (잘 기억해둡니다! jenkinsfile 작성 시 사용할 것 입니다.)</li>
<li><code class="language-plaintext highlighter-rouge">Description</code> : 부연 설명</li>
<li><code class="language-plaintext highlighter-rouge">Username</code> : ssh 접속 아이디</li>
<li><code class="language-plaintext highlighter-rouge">private key > Enter directly > key</code> : 복사한 pem file 문자열 붙여넣기</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_pipeline_credentials.png" alt="jenkins_pipeline_credentials" /></p>
<h3 id="5-10-jenkinsfilegroovy-작성">5-10. Jenkinsfile.groovy 작성</h3>
<p>5-7에서 생성한 groovy 파일에 아래 스크립트를 작성해줍니다. <br />
각 단계별로 간단하게 설명을 써놨는데 혹시 이해안가거나 부족한 부분이 있으면 질문 부탁드립니다!</p>
<div class="language-groovy highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">node</span> <span class="o">{</span>
<span class="kt">def</span> <span class="n">scmVars</span> <span class="o">=</span> <span class="n">checkout</span> <span class="n">scm</span>
<span class="kt">def</span> <span class="n">values</span> <span class="o">=</span> <span class="n">scmVars</span><span class="o">.</span><span class="na">GIT_BRANCH</span><span class="o">.</span><span class="na">tokenize</span><span class="o">(</span><span class="s1">'/'</span><span class="o">)</span>
<span class="n">String</span> <span class="n">branchName</span> <span class="o">=</span> <span class="n">values</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span> <span class="c1">// Gitlab으로 Push한 branch의 이름을 얻어 올 수 있습니다.</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">gitCheckout</span><span class="o">(</span><span class="n">branchName</span><span class="o">)</span>
<span class="n">srcBuild</span><span class="o">()</span>
<span class="n">unitTest</span><span class="o">()</span>
<span class="n">deploy</span><span class="o">()</span>
<span class="n">notifySlack</span><span class="o">(</span><span class="s1">'SUCCESS'</span><span class="o">)</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">env</span><span class="o">)</span> <span class="o">{</span>
<span class="n">notifySlack</span><span class="o">(</span><span class="s1">'FAIL'</span><span class="o">)</span>
<span class="k">throw</span> <span class="n">env</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="c1">// gitlab으로 부터 Source를 checkout 해옵니다.</span>
<span class="c1">// {CREDENTIALIS_ID}, ${GIT_URL}은 jenkins item 등록 시 추가해줬던 매개변수들이 대입됩니다.</span>
<span class="kt">def</span> <span class="nf">gitCheckout</span><span class="o">(</span><span class="n">String</span> <span class="n">branch</span><span class="o">)</span> <span class="o">{</span>
<span class="n">stage</span><span class="o">(</span><span class="s1">'Git Checkout'</span><span class="o">)</span> <span class="o">{</span>
<span class="n">echo</span> <span class="s1">'Checkout '</span> <span class="o">+</span> <span class="n">branch</span>
<span class="n">git</span> <span class="nl">branch:</span> <span class="n">branch</span><span class="o">,</span> <span class="nl">credentialsId:</span> <span class="s2">"${CREDENTIALIS_ID}"</span><span class="o">,</span> <span class="nl">url:</span> <span class="s2">"${GIT_URL}"</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="c1">// build를 진행합니다.</span>
<span class="kt">def</span> <span class="nf">srcBuild</span><span class="o">()</span> <span class="o">{</span>
<span class="n">stage</span><span class="o">(</span><span class="s1">'Build'</span><span class="o">)</span> <span class="o">{</span>
<span class="n">sh</span> <span class="s2">"./gradlew clean build"</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="c1">// 단위 테스트를 진행합니다.</span>
<span class="kt">def</span> <span class="nf">unitTest</span><span class="o">()</span> <span class="o">{</span>
<span class="n">stage</span><span class="o">(</span><span class="s1">'Unit tests'</span><span class="o">)</span> <span class="o">{</span>
<span class="n">sh</span> <span class="s2">"./gradlew test"</span>
<span class="k">if</span> <span class="o">(</span><span class="n">currentBuild</span><span class="o">.</span><span class="na">result</span> <span class="o">==</span> <span class="s2">"UNSTABLE"</span><span class="o">)</span> <span class="o">{</span>
<span class="n">notifySlack</span><span class="o">(</span><span class="s1">'UNSTABLE'</span><span class="o">)</span>
<span class="n">sh</span> <span class="s2">"exit 1"</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="c1">// SSH Agent 플러그인을 통해 배포를 진행합니다.</span>
<span class="c1">// credentials는 5-9에서 설정한 ID를 넣어줍니다.</span>
<span class="kt">def</span> <span class="nf">deploy</span><span class="o">()</span> <span class="o">{</span>
<span class="n">stage</span><span class="o">(</span><span class="s1">'Deploy'</span><span class="o">)</span> <span class="o">{</span>
<span class="n">sshagent</span><span class="o">(</span><span class="nl">credentials:</span> <span class="o">[</span><span class="s1">'aws-ec2-key'</span><span class="o">])</span> <span class="o">{</span>
<span class="n">sh</span> <span class="s1">'ssh -o StrictHostKeyChecking=no ubuntu@15.164.104.228 uptime'</span>
<span class="n">sh</span> <span class="s1">'scp -r build/libs/*.jar ubuntu@15.164.104.228:/home/ubuntu/demo'</span>
<span class="n">sh</span> <span class="s1">'ssh ubuntu@15.164.104.228 "sh /home/ubuntu/start.sh"'</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="c1">// 슬랙으로 노티를 보낼때 사용되는 함수입니다.</span>
<span class="kt">def</span> <span class="nf">notifySlack</span><span class="o">(</span><span class="n">String</span> <span class="n">buildStatus</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">def</span> <span class="n">color</span>
<span class="nf">if</span> <span class="o">(</span><span class="n">buildStatus</span> <span class="o">==</span> <span class="s1">'SUCCESS'</span><span class="o">)</span> <span class="o">{</span>
<span class="n">color</span> <span class="o">=</span> <span class="s1">'#1a9367'</span>
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">buildStatus</span> <span class="o">==</span> <span class="s1">'UNSTABLE'</span><span class="o">)</span> <span class="o">{</span>
<span class="n">color</span> <span class="o">=</span> <span class="s1">'#FFFE89'</span>
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
<span class="n">color</span> <span class="o">=</span> <span class="s1">'#ff0000'</span>
<span class="o">}</span>
<span class="kt">def</span> <span class="n">msg</span> <span class="o">=</span> <span class="s2">"${buildStatus}: `${env.JOB_NAME}` #${env.BUILD_NUMBER}:\n${env.BUILD_URL}"</span>
<span class="n">slackSend</span><span class="o">(</span><span class="nl">channel:</span> <span class="s2">"${SLACK_CHANNEL}"</span><span class="o">,</span> <span class="nl">color:</span> <span class="n">color</span><span class="o">,</span> <span class="nl">message:</span> <span class="n">msg</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div></div>
<h3 id="5-11-deploy-serveraws-ec2-설정">5-11. Deploy server(aws ec2) 설정</h3>
<p>잠깐 배포할 서버인 aws ec2로 ssh 접속해서 /home/ubuntu 밑에 <code class="language-plaintext highlighter-rouge">테스트 sh 파일</code>과 <code class="language-plaintext highlighter-rouge">demo 디렉토리</code>만 생성하겠습니다.</p>
<ul>
<li>sh 파일은 <code class="language-plaintext highlighter-rouge">echo "test"</code>만 작성한 의미 없는 shell 파일입니다.</li>
<li>이번 시간에는 jenkins에서 빌드 후 결과물이 배포할 서버에 제대로 delivery 되는지만 체크하기 위해 의미 없는 값을 넣었습니다.</li>
<li>실제 상용에서는 실행 중인 프로세스를 멈추고 새 빌드 결과물로 기동을 하는 등의 스크립트 파일을 넣어 줄 수 있을 것입니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/ec2_mkdir.png" alt="ec2_mkdir" /></p>
<h3 id="5-12-git-push">5-12. Git Push</h3>
<p>Jenkinsfile.goorvy 파일이 생성 및 작성된 상태로 gitlab으로 push하면 jenkins에서 자동으로 빌드를 수행하는 것을 확인할 수 있습니다.</p>
<ul>
<li>(테스트하느라 빌드 번호가 6번인데 원래는 1번일 것입니다!)</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_pipeline_build_ing.png" alt="jenkins_pipeline_build_ing" /></p>
<h3 id="5-13-result">5-13. Result</h3>
<p>빌드가 성공하고 해당 인스턴스로 ssh 접속해보면 빌드 결과물인 jar 파일이 있는 것을 확인 하실 수 있습니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/build_result_file_pipeline.png" alt="build_result_file_pipeline" /></p>
<p>또한, 슬랙으로 성공 메시지가 전송될 것 입니다.</p>
<h2 id="마무리">마무리</h2>
<p>이번 시간에는 파이프라인 스크립트를 이용해서 젠킨스 item을 등록해보았습니다. <br />
Web UI를 통해 item을 등록하는 방식에 비해 훨씬 간단하지 않으셨나요? <br />
이렇게 공통 매개 변수를 빼고 동일한 Jenkinsfile.groovy 파일을 사용한다면 수정 및 추가 사항이 있을 때 UI를 이용해 등록하는 방식보다 훨씬 간단할 것입니다. <br />
또한, 최근에는 인프라에 관한 설정들이 소스 코드 단으로 내려오는 추세이기도 하고 젠킨스에서도 pipeline을 이용한 방식을 추천하고 있기 때문에 파이프라인 사용을 적극 추천드립니다. <br />
Jenkinsfile.groovy 파일은 각자의 요구사항에 맞게끔 수정해서 사용하면 될 것 같은데 소스에 대한 설명이 조금 빈약해서 혹시 궁금하신 점이 있으면 댓글 남겨주시기 바랍니다. <br />
지금까지 총 5편의 Jenkins tutorial을 작성해보았는데 제가 한 방식이 정답은 아니라고 생각합니다. 더 좋고 유연한 방식이 많을 것인데 그중 하나라고 봐주시면 좋을 것 같습니다. <br />
읽어주셔서 감사합니다 :)</p>sungjunJenkins pipeline을 이용해 아이템 등록 하기4) Jenkins Tutorial - Registering Jenkins items using web ui2019-04-16T00:00:00+00:002019-04-16T00:00:00+00:00https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_4<p>Jenkins UI를 이용해 아이템 등록 하기</p>
<hr />
<p>이번 시간에는 Jenkins Web UI를 이용해서 실제 item을 등록해보도록 하겠습니다. <br />
전체적인 흐름은 다음과 같습니다. 참고해주시기 바랍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_flow.png" alt="jenkins_flow" /></p>
<h2 id="contents">Contents</h2>
<ol>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_1">Installing Jenkins and GitLab with Docker</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_2">Jenkins, GitLab initial setting</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_3">Create AWS EC2 Instance</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_4">Registering Jenkins items using web ui</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_5">Registering Jenkins items using pipeline</a></li>
</ol>
<h2 id="4-registering-jenkins-items-using-web-ui">4. Registering Jenkins items using web ui</h2>
<h3 id="4-1-publish-over-ssh-plugin-설치">4-1. Publish Over SSH Plugin 설치</h3>
<p>Jenkins 관리 > 플러그인 관리로 이동해서 아래와 같이 <code class="language-plaintext highlighter-rouge">Publish Over SSH</code> 플러그인을 설치합니다.</p>
<ul>
<li>‘지금 다운로드하고 재시작 후 설치하기’ > ‘설치가 끝나고 실행중인 작업이 없으면 Jenkins 재시작’ 버튼 체크</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_publish-over-ssh.png" alt="jenkins_publish-over-ssh" /></p>
<h3 id="4-2-jenkins-publish-over-ssh-설정">4-2. Jenkins Publish Over SSH 설정</h3>
<p>먼저, 이전에 생성해둔 AWS EC2 Instance 키페어가 저장된 위치로 이동합니다. <br />
아래와 같이 cat 명령을 통해 pem file을 출력하고 출력된 문자열을 복사합니다.</p>
<ul>
<li>복사하실 때는 —–BEGIN RSA PRIVATE KEY—–부터 —–END RSA PRIVATE KEY—–까지 모두 복사해야 합니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/cat_pem.png" alt="cat_pem" /></p>
<p>다음, Jenkins 관리 > 시스템 설정 > Publish Over SSH 항목으로 이동합니다. <br />
Key에는 방금 복사한 문자열(pem file)을 붙여넣고 <code class="language-plaintext highlighter-rouge">추가</code> 버튼을 눌러 아래와 같이 자신에게 맞는 정보를 입력합니다.</p>
<ul>
<li>실제 상용에서는 지금처럼 사용하면 키값을 그대로 노출할 수 있어 많이 취약한 방법입니다.</li>
<li>해당 키를 적절한 디렉토리(/var/lib/jenkins/.ssh/)에 이동시키고 path 설정을 통해 키를 읽도록 하는 것이 가장 안전합니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins-over-ssh-setting.png" alt="jenkins-over-ssh-setting" /></p>
<ul>
<li>Name: Job에서 표시될 이름 지정</li>
<li>Hostname: IP Address</li>
<li>Username: SSH 접근 계정</li>
<li>Remote Directory: 업로드될 디렉토리 (여러개가 있다면 상위만 지정)</li>
</ul>
<p>Test Configuration을 눌러 <code class="language-plaintext highlighter-rouge">Success</code>가 떨어지면 저장버튼을 눌러 적용시킵니다.</p>
<h3 id="4-3-새로운-item-등록">4-3. 새로운 Item 등록</h3>
<p>Jenkins > 새로운 Item을 클릭하고 아래와 같이 <code class="language-plaintext highlighter-rouge">item 이름</code> 지정, <code class="language-plaintext highlighter-rouge">Freestyle project</code>를 선택한 뒤 <code class="language-plaintext highlighter-rouge">OK</code> 버튼을 누릅니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_new_item.png" alt="jenkins_new_item" /></p>
<h3 id="4-4-general-설정">4-4. General 설정</h3>
<p>General에는 해당 item을 간단하게 설명해줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_general.png" alt="jenkins_general" /></p>
<h3 id="4-5-소스-코드-관리-설정">4-5. 소스 코드 관리 설정</h3>
<p>소스 코드 관리는 <code class="language-plaintext highlighter-rouge">Git</code>을 선택해줍니다. <br />
그리고 Credentials 셀렉트박스 옆에 <code class="language-plaintext highlighter-rouge">Add</code> 버튼을 클릭하고 <code class="language-plaintext highlighter-rouge">jenkins</code>를 선택합니다. <br />
아래와 같이 Kind는 <code class="language-plaintext highlighter-rouge">Username with password</code>를 선택하고 Username과 Password에 gitlab 아이디 패스워드를 입력합니다. <br />
ID는 Jenkins 내에서 식별할 아이디, Description은 해당 ID에 대한 설명을 입력해줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_add_credential.png" alt="jenkins_add_credential" /></p>
<p>Credentials를 추가하였다면 해당 Credentials를 선택해주고 <code class="language-plaintext highlighter-rouge">Reposiroty URL</code>에는 gitlab 프로젝트 주소를 입력합니다. <br />
현재는 gitlab URL을 docker private ip로 등록해야 합니다. (실제 상용에서는 이렇게 사용하시면 안됩니다!)</p>
<ul>
<li>2편에서 보셨던것 처럼 <code class="language-plaintext highlighter-rouge">docker inspect gitlab | grep "IPAddress"</code> 명령을 통해 나오는 IP를 입력합니다.</li>
<li>프로젝트 URL의 gitlab.example.com 부분을 172.18.0.2와 같은 Docker private IP로 변경해줍니다.
또한, 현재 브랜치는 master 브랜치 밖에 없기 때문에 기본 설정(*/master) 그대로 유지합니다. (여러 브랜치에서의 설정은 나중에 설명드리도록 하겠습니다.)</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_source_code.png" alt="jenkins_source_code" /></p>
<h3 id="4-6-빌드-유발-설정">4-6. 빌드 유발 설정</h3>
<p>빌드 유발은 <code class="language-plaintext highlighter-rouge">Build when a change is pushed to GitLab</code> 을 선택해줍니다. <br />
그리고 고급 버튼을 눌러 Secret token의 <code class="language-plaintext highlighter-rouge">Generate 버튼</code>을 클릭합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_build_trigger.png" alt="jenkins_build_trigger" /></p>
<p>잠깐 GitLab에 접속해서 <code class="language-plaintext highlighter-rouge">Admin area > settings > network > Outbound requests</code>로 이동하여 <code class="language-plaintext highlighter-rouge">Allow request to the local network from hooks and services</code>를 체크해준 뒤 저장합니다.</p>
<ul>
<li>이 설정을 해주지 않으면 아래 Integrations 설정 시 “Requests to the local network are not allowed” 에러가 발생합니다. (로컬 테스트 시만 체크하시고 상용환경에서는 생략하시고 넘어가면 됩니다.)</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_outbound.png" alt="gitlab_outbound" /></p>
<p>다음, Gitlab 해당 Project > settings > Integrations로 이동하겠습니다. <br />
그리고 URL은 위에서 체크했던 <code class="language-plaintext highlighter-rouge">Build when a change is pushed to GitLab. GitLab webhook URL:</code> 부분의 url 부분만 복사해서 넣습니다.</p>
<ul>
<li>url에서 localhost 부분은 <code class="language-plaintext highlighter-rouge">docker inspect jenkins | grep "IPAddress"</code>를 입력해서 나오는 IP로 바꿔줍니다. (매번 수정해 넣기 불편하긴 하네요. 테스트하기 쉽게 젠킨스와 깃랩을 로컬에서 도커로 띄워서 어쩔 수 없을 것 같습니다. 😥)
secret token 역시 젠킨스에서 생성한 token을 입력합니다. <br />
적절한 Trigger를 선택해주면 되는데 현재는 Push events만 선택하겠습니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_integrations.png" alt="gitlab_integrations" /></p>
<h3 id="4-7-빌드-환경-설정">4-7. 빌드 환경 설정</h3>
<p>다시 젠킨스로 돌아와 빌드 환경의 <code class="language-plaintext highlighter-rouge">Send files or execute commands over SSH after the build runs</code>를 선택합니다.</p>
<ul>
<li>Name: Jenkins 시스템 설정에서 등록한 SSH 서버 중 배포할 서버를 선택합니다.</li>
<li>Sources files : jar 혹은 war가 빌드된 위치를 적습니다. ex) build/libs/*.jar</li>
<li>Remove prefix : 파일 앞부분에 경로부분을 적습니다. ex) build/libs</li>
<li>Remote directory : 업로드될 경로입니다.
<ul>
<li>주의할 것은 위의 4-2 Publish Over SSH 설정에서 Remote Directory 내의 디렉토리를 적어야 합니다.</li>
<li>예를들어, 최종 경로가 /hom/ubuntu/demo 라면 => 이미 위에서 /home/ubuntu를 적었기에 여기에는 demo 만 적어야 합니다.</li>
</ul>
</li>
<li>Exec command : 실행할 명령어를 적으면 됩니다. ex) sh start.sh</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_build_env.png" alt="jenkins_build_env" /></p>
<h3 id="4-8-빌드-설정">4-8. 빌드 설정</h3>
<p>빌드는 Add build step > <code class="language-plaintext highlighter-rouge">Execute shell</code>을 선택하고 command에 <code class="language-plaintext highlighter-rouge">./gradlew build</code>를 넣어줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_build.png" alt="jenkins_build" /></p>
<h3 id="4-9-빌드-후-조치-설정">4-9. 빌드 후 조치 설정</h3>
<p>빌드 결과를 슬랙으로 전송받기 위해 마지막으로 빌드 후 조치 추가 > <code class="language-plaintext highlighter-rouge">Slack notifications</code>를 선택해 설정을 해줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/slack_notify.png" alt="slack_notify" /></p>
<p>슬랙 Noti 설정까지 끝내고 저장을 하시면 드디어 하나의 item 등록이 완료 되었습니다.</p>
<h3 id="4-10-deploy-serveraws-ec2-설정">4-10. Deploy server(aws ec2) 설정</h3>
<p>잠깐 배포할 서버인 aws ec2로 ssh 접속해서 /home/ubuntu 밑에 <code class="language-plaintext highlighter-rouge">테스트 sh 파일</code>과 <code class="language-plaintext highlighter-rouge">demo 디렉토리</code>만 생성하겠습니다.</p>
<ul>
<li>sh 파일은 <code class="language-plaintext highlighter-rouge">echo "test"</code>만 작성한 의미 없는 shell 파일입니다.</li>
<li>이번 시간에는 jenkins에서 빌드 후 결과물이 배포할 서버에 제대로 delivery 되는지만 체크하기 위해 의미 없는 값을 넣었습니다.</li>
<li>실제 상용에서는 실행 중인 프로세스를 멈추고 새 빌드 결과물로 기동을 하는 등의 스크립트 파일을 넣어 줄 수 있을 것입니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/ec2_mkdir.png" alt="ec2_mkdir" /></p>
<h3 id="4-11-git-push">4-11. Git Push</h3>
<p>소스를 조금 수정하고 push하면 jenkins에서 자동으로 빌드를 수행하는 것을 확인할 수 있습니다.</p>
<ul>
<li>(여러 번 테스트하느라 빌드 번호가 12번인데 원래는 1번일 것입니다!)</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_build_ing.png" alt="jenkins_build_ing" /></p>
<h3 id="4-12-result">4-12. Result</h3>
<p>빌드가 성공하고 해당 인스턴스로 ssh 접속해보면 빌드 결과물인 jar 파일이 있는 것을 확인 하실 수 있습니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/build_result_file.png" alt="build_result_file" /></p>
<p>또한, 슬랙으로 아래와 같이 성공 메시지가 전송될 것 입니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/success_slack_message.png" alt="success_slack_message" /></p>
<h2 id="마무리">마무리</h2>
<p>이번 시간에는 실제 젠킨스 item을 등록해보았습니다. <br />
실제 item을 등록해보니 어떤 신가요? 사용하는데 번거롭거나 불편하진 않으셨나요? <br />
Web UI를 통해 item을 등록하는 방식은 사용자가 배포할 서버를 추가하거나 빌드 스크립트에 수정 사항이 있는 등 변경 사항이 있을 때 마다 웹에 접속하여 일일이 바꿔줘야 합니다. 여러 item이 공통적인 내용을 담고 있다면 더 곤란해질 것입니다. <br />
이를 해결하고자 jenkins pipeline을 사용해볼 것 인데요. 자세한 것은 다음 시간에 소개하도록 하겠습니다. <br />
감사합니다. 궁금한 점이 있으시거나 잘못된 점이 있다면 댓글 남겨 주시기 바랍니다.</p>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://hreeman.tistory.com/m/136">https://hreeman.tistory.com/m/136</a></li>
<li><a href="https://yookeun.github.io/tools/2018/04/14/jenkins-remote/">https://yookeun.github.io/tools/2018/04/14/jenkins-remote/</a></li>
</ul>sungjunJenkins UI를 이용해 아이템 등록 하기2) Jenkins Tutorial - Jenkins, GitLab initial setting2019-04-12T00:00:00+00:002019-04-12T00:00:00+00:00https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_2<p>젠킨스, 깃랩 초기 설정</p>
<hr />
<p>지난 <a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_1">1편</a>에서 젠킨스와 깃랩을 설치해보았습니다. <br />
이번 시간에는 젠킨스와 깃랩의 기본 설정 작업을 진행해보도록 하겠습니다.</p>
<h2 id="contents">Contents</h2>
<ol>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_1">Installing Jenkins and GitLab with Docker</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_2">Jenkins, GitLab initial setting</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_3">Create AWS EC2 Instance</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_4">Registering Jenkins items using web ui</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_5">Registering Jenkins items using pipeline</a></li>
</ol>
<h2 id="2-jenkins-gitlab-initial-setting">2. Jenkins, GitLab initial setting</h2>
<h3 id="2-1-jenkins-로그인">2-1. Jenkins 로그인</h3>
<p>젠킨스를 설치 후 처음 접속하게 되면 지난 1편 마지막에 보인 이미지처럼 Unlock Jnekins 화면이 보입니다. <br />
따라서, lock 해제를 위해 젠킨스 컨테이너 안의 bash 셸로 연결하고 아래 cat 명령을 통해 Administrator password를 확인합니다.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker <span class="nb">exec</span> <span class="nt">-it</span> jenkins /bin/bash
<span class="nv">$ </span><span class="nb">cat</span> /var/jenkins_home/secrets/initialAdminPassword
6a85c6fa37644529a7426863a701784d
</code></pre></div></div>
<ul>
<li>출력되는 password를 jnekins password 입력창에 copy & paste 합니다.</li>
</ul>
<p>이다음 절차는 이전에 제가 작성한 <a href="https://gwonsungjun.github.io/articles/2018-04/jenkinsInstall">Ubuntu 16.04 Jenkins 설치</a> 글을 참조하여 플러그인 설치 및 계정 생성을 통해 로그인하도록 합니다.</p>
<h3 id="2-2-jenkins-플러그인-설치">2-2. Jenkins 플러그인 설치</h3>
<p>Jenkins 첫 메인 화면에서 Jenkin 관리 > 플러그인 관리로 이동합니다. <br />
설치 가능 탭을 선택하고 <code class="language-plaintext highlighter-rouge">gitlab</code>을 검색한 뒤 아래 그림과 같이 <code class="language-plaintext highlighter-rouge">GitLab</code>을 선택합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_plugin_gitlab.png" alt="jenkins_plugin_gitlab" /></p>
<p>다음 <code class="language-plaintext highlighter-rouge">slack</code>을 검색해서 <code class="language-plaintext highlighter-rouge">Slack Notification</code>을 선택한 뒤 “지금 다운로드하고 재시작 후 설치하기”를 클릭합니다.</p>
<ul>
<li>Slack Notification은 차후에 젠킨스 빌드 결과를 slack으로 전송할 것이기 때문에 미리 설치합니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_plugin_slack.png" alt="jenkins_plugin_slack" /></p>
<p>마지막으로 <code class="language-plaintext highlighter-rouge">설치가 끝나고 실행 중인 작업이 없으면 Jenkins 재시작</code>을 체크한 뒤 설치가 완료되면 jenkins가 재시작되도록 합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_plugin_installing.png" alt="jenkins_plugin_installing" /></p>
<p>젠킨스에 재접속한 뒤 플러그인 관리의 설치된 플러그인 목록을 보면 GitLab와 Slack Notification 플러그인이 설치되어 있을 것입니다.</p>
<h3 id="2-3-jenkins-jenkins-ci-apps-설치">2-3. Jenkins Jenkins CI Apps 설치</h3>
<p>slack worksapce는 테스트로 생성해준 뒤 채널 목록부분 아래 Apps 옆에 +를 클릭합니다. <br />
jenkins를 검색하고 Install를 눌려주면 Jenkins CI 설치를 위한 브라우저 창이 열립니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/slack_jenkins_install_1.png" alt="slack_jenkins_install_1" /></p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/slack_jenkins_install_2.png" alt="slack_jenkins_install_2" /></p>
<p>Jenkins 빌드 결과 받을 채널을 생성해준 뒤 선택하고 “Add Jenkins CI integration” 버튼을 클릭합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/slack_jenkins_install_3.png" alt="slack_jenkins_install_3" /></p>
<p>마지막으로 “Setup Instr/uctions” 페이지를 확인할 수 있는데 잠시 켜둔 채 다시 젠킨스로 이동합니다.</p>
<h3 id="2-4-jenkins-slack-연동">2-4. Jenkins Slack 연동</h3>
<p>Jenkins 관리 > 시스템 설정 > 맨 아래 <code class="language-plaintext highlighter-rouge">Global Slack Notifier Settings</code>으로 이동합니다. <br />
Integration Token Credential ID 옆에 <code class="language-plaintext highlighter-rouge">Add</code> 버튼을 클릭해서 2-3 마지막에 켜둔 Setup Instr/uctions 페이지의 Step 3 Integration Token을 아래와 같이 secret 부분에 입력합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_slack_integration_1.png" alt="jenkins_slack_integration_1" /></p>
<p>Step 3 Base URL을 Slack compatible app URL에 입력하고 Channel or Slack ID는 젠킨스 빌드 결과를 받기 위해 생선한 slack 채널명을 입력합니다. <br />
Test Connection 버튼을 클릭했을 때 success가 떨어지면 저장하도록 합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_slack_integration_2.png" alt="jenkins_slack_integration_2" /></p>
<ul>
<li>(+) 여러개의 슬랙 채널을 사용하는 방법 : comma separated(,)를 이용해서 등록 가능합니다.</li>
</ul>
<h3 id="2-5-gitlab-로그인-및-프로젝트-생성">2-5. GitLab 로그인 및 프로젝트 생성</h3>
<p>GitLab으로 접속하여 패스워드를 설정해주고 로그인합니다.</p>
<ul>
<li>default ID는 root입니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_login.png" alt="gitlab_login" /></p>
<p>“Create a project”를 클릭하여 프로젝트를 새롭게 생성합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_create_project.png" alt="gitlab_create_project" /></p>
<p>프로젝트 이름 등 정보를 입력하고 “Create project”를 클릭합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_new_project.png" alt="gitlab_new_project" /></p>
<p>데모 프로젝트는 <a href="https://github.com/gwonsungjun/demo-springboot">GitHub Sample project</a>를 내려받아서 사용하시면 됩니다.</p>
<ul>
<li>간단하게 hello world를 출력하는 spring boot로 작성된 프로젝트입니다.</li>
</ul>
<p>데모 프로젝트를 내려받고 아래 명령을 통하여 GitLab에 Push를 합니다.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>existing_folder
git init
git remote add origin http://localhost/root/test.git
git add <span class="nb">.</span>
git commit <span class="nt">-m</span> <span class="s2">"Initial commit"</span>
git push <span class="nt">-u</span> origin master
</code></pre></div></div>
<ul>
<li>아래와 같이 프로젝트 소스가 정상적으로 올라오면 성공입니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_project.png" alt="gitlab_project" /></p>
<h3 id="2-6-gitlab-access-token-생성">2-6. GitLab Access Token 생성</h3>
<p>Gitlab > User settings > Access Tokens로 이동합니다. <br />
Name, Expires at, Scopes를 선택 및 입력하고 Create personal access token 클릭하여 상단에 생성된 토큰을 복사합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab_accesstoken.png" alt="gitlab_accesstoken" /></p>
<h3 id="2-7-jenkins-credentials-등록">2-7. Jenkins Credentials 등록</h3>
<p>왼쪽 메뉴에서 Credentials > System > Global credentials > Add Credentials를 클릭해서 2-6에서 복사한 GitLab API token을 등록해줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_credential.png" alt="jenkins_credential" />
<img src="/assets/images/usingimages/jenkins_tutorial/jenkins_credential_gitlab.png" alt="jenkins_credential_gitlab" /></p>
<ul>
<li>Kind : GitLab API token</li>
<li>Scope : Global</li>
<li>방금 위에서 GitLab에서 복사한 Access Token, API token에 붙여넣기</li>
<li>ID, Description 입력 후 OK</li>
</ul>
<h3 id="2-8-jenkins-gitlab-connection">2-8. Jenkins GitLab Connection</h3>
<p>왼쪽 메뉴 Jenkins 관리 > 시스템 설정 > GitLab에서 GitLab connections를 설정합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins_gitlab_connect.png" alt="jenkins_gitlab_connect" /></p>
<ul>
<li>Connection name : 식별할 수 있는 값 입력</li>
<li>GitLab Host URL
<ul>
<li><code class="language-plaintext highlighter-rouge">docker inspect gitlab | grep "IPAddress"</code> 명령을 입력해서 나오는 IP를 입력한다.</li>
<li>도커 컨테이너의 private IP는 유동적으로 바뀌기 때문에 매번 바꿔줘야 하는 불편함이 있다. 따라서 로컬 테스트일 경우만 사용하고 실제 상용 서비스일 경우 gitlab의 도메인 주소를 입력해주면 된다.</li>
</ul>
</li>
<li>Credentials : 위 2-7에서 생성한 Credentials를 등록</li>
<li>Test Connection > Success 확인되면 SAVE</li>
</ul>
<h2 id="마무리">마무리</h2>
<p>이번 시간에는 젠킨스와 깃랩의 기본 설정을 해보았습니다. <br />
젠킨스와 깃랩을 처음 접하시는 분들은 조금 복잡해 보일 수도 있다고 생각합니다. 궁금한 점이 있으면 언제나 댓글에 질문을 남겨주세요. <br />
다음 시간에는 배포할 서버(AWS EC2)를 생성해보도록 하겠습니다.
감사합니다.</p>sungjun젠킨스, 깃랩 초기 설정3) Jenkins Tutorial - Create AWS EC2 Instance2019-04-12T00:00:00+00:002019-04-12T00:00:00+00:00https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_3<p>AWS EC2 Instance 생성</p>
<hr />
<p>이번 시간에는 배포할 서버를 AWS EC2로 생성해보겠습니다.</p>
<h2 id="contents">Contents</h2>
<ol>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_1">Installing Jenkins and GitLab with Docker</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_2">Jenkins, GitLab initial setting</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_3">Create AWS EC2 Instance</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_4">Registering Jenkins items using web ui</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_5">Registering Jenkins items using pipeline</a></li>
</ol>
<h2 id="3-create-aws-ec2-instance">3. Create AWS EC2 Instance</h2>
<h3 id="3-1-리전-변경">3-1. 리전 변경</h3>
<p>먼저, AWS Console에 로그인해서 리전을 아시아 태평양(서울)로 변경해줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_1.png" alt="aws_1" /></p>
<h3 id="3-2-ec2-인스턴스-생성">3-2. EC2 인스턴스 생성</h3>
<p>서비스 > EC2를 선택합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_2.png" alt="aws_2" /></p>
<p>인스턴스 시작 버튼을 눌러줍니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_3.png" alt="aws_3" /></p>
<h3 id="3-3-amiamazon-machine-image-선택">3-3. AMI(Amazon Machine Image) 선택</h3>
<p>저는 <code class="language-plaintext highlighter-rouge">Ubuntu Server 18.04 LTS</code>를 선택하겠습니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_4.png" alt="aws_4" /></p>
<h3 id="3-4-인스턴스-유형-선택">3-4. 인스턴스 유형 선택</h3>
<p><code class="language-plaintext highlighter-rouge">프리티어 사용 가능 표시</code>가 있는 t2.micro를 선택하고 <code class="language-plaintext highlighter-rouge">다음:인스턴스 세부 정보 구성</code> 버튼을 클릭합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_5.png" alt="aws_5" /></p>
<h3 id="3-5-보안-그룹-구성-및-검토">3-5. 보안 그룹 구성 및 검토</h3>
<p>인스턴스 구성, 스토리지 추가, 태그 추가, 보안 그룹 구성은 다음 버튼을 눌러 SKIP 합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_6.png" alt="aws_6" /></p>
<h3 id="3-5-새-키-페어-생성">3-5. 새 키 페어 생성</h3>
<p>인스턴스 시작을 위해 키 페어를 생성해야합니다.</p>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_7.png" alt="aws_7" /></p>
<h3 id="3-6-인스턴스-생성-완료">3-6. 인스턴스 생성 완료</h3>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_8.png" alt="aws_8" /></p>
<h3 id="3-7-인스턴스-원격-접속">3-7. 인스턴스 원격 접속</h3>
<ul>
<li>다운로드한 키 파일(.pem)을 적당한 디렉토리로 이동시킨 후 권한 변경을 해줍니다.
<ul>
<li><code class="language-plaintext highlighter-rouge">$ chmod 400 jenkins-demo.pem</code></li>
</ul>
</li>
<li>$ ssh -i pem경로 user-name@public-dns-name 명령을 통해 원격 접속을 합니다.
<ul>
<li>Ubuntu AMI의 경우, user-name은 ubuntu 입니다.</li>
<li>public-dns-name은 aws ec2 퍼블릭 DNS(IPv4) 값을 가져옵니다.</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_9.png" alt="aws_9" /></p>
<ul>
<li><code class="language-plaintext highlighter-rouge">ssh -i jenkins-demo.pem ubuntu@ec2-13-125-216-1.ap-northeast-2.compute.amazonaws.com</code></li>
</ul>
</li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/aws_welcome.png" alt="aws_welcome" /></p>
<ul>
<li>windows 운영체제의 경우 putty를 이용하여 접속 할 수 있습니다.</li>
</ul>
<h2 id="마무리">마무리</h2>
<p>이번 시간에는 간단하게 AWS EC2 인스턴스를 생성해보았습니다. <br />
다음 시간에는 실제 Jenkins item을 등록해보도록 하겠습니다. <br />
감사합니다.</p>sungjunAWS EC2 Instance 생성1) Jenkins Tutorial - Installing Jenkins and GitLab with Docker2019-04-09T00:00:00+00:002019-04-09T00:00:00+00:00https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_1<p>도커 컴포즈를 이용해 젠킨스, 깃랩 설치하기</p>
<hr />
<p>이번 시리즈 글은 수많은 삽질을 통해 젠킨스를 사내에 구축하며 얻은 유용한 팁을 젠킨스를 처음 접하는 분들께 도움이 되고자 작성하게 되었습니다. <br />
Tutorial은 블로그에 단계별로 나눠 포스팅할 예정이고 pipeline script 외 기타 필요한 코드들을 <a href="https://github.com/gwonsungjun/jenkins_tutorial">GitHub Repo</a>에 커밋할 것입니다. <br />
Git Hosting service는 깃헙이 아닌 깃랩을 직접 설치해서 사용할 것입니다. (깃헙과 깃랩은 거의 유사하기 때문에 필요한 호스팅 서비스를 사용하면 될 것 같습니다.)</p>
<h2 id="개발환경">개발환경</h2>
<ul>
<li>IDE : Intellij IDEA Ultimate</li>
<li>OS : Mac OS X</li>
<li>Spring boot 2.1.3.RELEASE</li>
<li>Java8</li>
<li>Gradle</li>
<li>docker 18.09.2</li>
<li>docker-compose 1.23.2</li>
</ul>
<h2 id="contents">Contents</h2>
<ol>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_1">Installing Jenkins and GitLab with Docker</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_2">Jenkins initial setting</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_3">Create AWS EC2 Instance</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_4">Registering Jenkins items using web ui</a></li>
<li><a href="https://gwonsungjun.github.io/articles/2019-04/jenkins_tutorial_5">Registering Jenkins items using pipeline</a></li>
</ol>
<h2 id="1-installing-jenkins-and-gitlab-with-docker">1. Installing Jenkins and GitLab with Docker</h2>
<h3 id="1-1-docker-설치">1-1. Docker 설치</h3>
<p>운영체제별로 설치 방법이 다르므로 자신의 환경에 맞게 설치합니다.</p>
<h4 id="windows">Windows</h4>
<ul>
<li><a href="https://docs.docker.com/docker-for-mac/install/">Windows 10 : Pro, Enterprise or Education</a></li>
<li>Windows 10 : Home
<ul>
<li>이전에 작성한 <a href="https://gwonsungjun.github.io/articles/2018-01/DockerInstall">Windows 10 Home에서 Docker 설치 하기</a> 글을 참조</li>
</ul>
</li>
</ul>
<h4 id="macos">MacOS</h4>
<ul>
<li><a href="https://docs.docker.com/docker-for-mac/install/">https://docs.docker.com/docker-for-mac/install/</a> 참고</li>
</ul>
<h4 id="linux">Linux</h4>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-fsSL</span> https://get.docker.com/ | <span class="nb">sudo </span>sh
<span class="nb">sudo </span>usermod <span class="nt">-aG</span> docker <span class="nv">$USER</span> <span class="c"># sudo 없이 사용, 현재 접속중인 사용자에게 권한주기</span>
<span class="c"># 재로그인 시 적용됨</span>
docker <span class="nt">-v</span>
</code></pre></div></div>
<h3 id="1-2-docker-compose-설치">1-2. Docker compose 설치</h3>
<p>Windows와 Mac의 경우는 docker 설치 시 docker compose가 기본적으로 포함되어 있을 것입니다.</p>
<h4 id="linux-1">Linux</h4>
<ul>
<li><a href="https://github.com/docker/compose/releases">https://github.com/docker/compose/releases</a> 접속하여 Latest release 버전을 확인합니다.</li>
<li>2019.04.09 기준 1.24.0 최신 버전 (최신 버전 확인 후 아래 curl 명령 download 뒤에 버전을 변경)</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-L</span> <span class="s2">"https://github.com/docker/compose/releases/download/1.24.0/docker-compose-</span><span class="si">$(</span><span class="nb">uname</span> <span class="nt">-s</span><span class="si">)</span><span class="s2">-</span><span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span><span class="s2">"</span> <span class="nt">-o</span> /usr/local/bin/docker-compose
<span class="c"># Access 권한 설정</span>
<span class="nb">chmod</span> +x /usr/local/bin/docker-compose
<span class="c"># test</span>
docker-compose version
</code></pre></div></div>
<h3 id="1-3-jenkins-dockerfile-작성">1-3. Jenkins Dockerfile 작성</h3>
<ul>
<li>dockerfile과 docker-compose 차이는 간단하게 설명하면 아래와 같고 자세한 설명은 <a href="https://docs.docker.com/compose/overview/">docker compose 공식 문서</a>를 참고합니다.
<ul>
<li>dockerfile : 이미지를 만드는 도구</li>
<li>docker-compose : 컨테이너를 만드는 도구</li>
</ul>
</li>
<li>나중에 설명할 것이지만 배포를 위해 zip, aws 명령이 필요합니다.</li>
</ul>
<p><code class="language-plaintext highlighter-rouge">vi Dockerfile-jenkins</code></p>
<div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 1. Jenkins Long Term Support(LTS) 이미지 생성</span>
<span class="k">FROM</span><span class="s"> jenkins/jenkins:lts</span>
<span class="c"># 2. 명령을 실행할 사용자 설정</span>
<span class="k">USER</span><span class="s"> root</span>
<span class="c"># 3. Jenkins build 시 필요한 zip command install</span>
<span class="k">RUN </span>apt-get update
<span class="k">RUN </span>apt-get <span class="nb">install</span> <span class="nt">-y</span> zip
<span class="c"># 4.Jenkins build 시 필요한 awscli command install</span>
<span class="k">RUN </span>apt-get <span class="nb">install</span> <span class="nt">-y</span> python-pip
<span class="k">RUN </span>pip <span class="nb">install </span>awscli
<span class="k">RUN </span>pip <span class="nb">install</span> <span class="nt">--upgrade</span> pip
</code></pre></div></div>
<h3 id="1-4-docker-composeyml-작성">1-4. docker-compose.yml 작성</h3>
<ul>
<li>version : <a href="https://docs.docker.com/compose/compose-file/">https://docs.docker.com/compose/compose-file/</a></li>
<li>image : 도커 컨테이너의 기반이 되는 베이스 이미지를 지정</li>
<li>build : Dockerfile에 이미지 구성을 저장하고 이를 자동으로 build 하여 베이스 이미지로 지정</li>
<li>port : YAML은 xx:yy형식을 시간으로 인식하므로 포트 번호를 설정할 때 다음과 같이 꼭 쌍따옴표(““)안에서 문자열을 입력해야 함</li>
<li>volumes : 컨테이너의 볼륨을 마운트</li>
</ul>
<p>Dockerfile-jenkins와 동일 디렉토리에서 <code class="language-plaintext highlighter-rouge">vi docker-compose.yml</code></p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">version</span><span class="pi">:</span> <span class="s2">"</span><span class="s">3.7"</span>
<span class="na">services</span><span class="pi">:</span>
<span class="err"> </span><span class="na">jenkins</span><span class="pi">:</span>
<span class="err"> </span><span class="na">build</span><span class="pi">:</span>
<span class="err"> </span><span class="na">context</span><span class="pi">:</span> <span class="s">.</span>
<span class="err"> </span><span class="na">dockerfile</span><span class="pi">:</span> <span class="s">Dockerfile-jenkins</span>
<span class="err"> </span><span class="na">container_name</span><span class="pi">:</span> <span class="s">jenkins</span>
<span class="err"> </span><span class="na">restart</span><span class="pi">:</span> <span class="s">always</span>
<span class="err"> </span><span class="na">user</span><span class="pi">:</span> <span class="s">root</span>
<span class="err"> </span><span class="na">ports</span><span class="pi">:</span>
<span class="err"> </span><span class="pi">-</span> <span class="s2">"</span><span class="s">8080:8080"</span>
<span class="err"> </span><span class="na">volumes</span><span class="pi">:</span>
<span class="err"> </span><span class="pi">-</span> <span class="s2">"</span><span class="s">/home/jenkins/jenkins_home:/var/jenkins_home"</span>
<span class="err"> </span><span class="na">gitlab</span><span class="pi">:</span>
<span class="err"> </span><span class="na">image</span><span class="pi">:</span> <span class="s2">"</span><span class="s">gitlab/gitlab-ce:latest"</span>
<span class="err"> </span><span class="na">container_name</span><span class="pi">:</span> <span class="s">gitlab</span>
<span class="err"> </span><span class="na">restart</span><span class="pi">:</span> <span class="s">always</span>
<span class="err"> </span><span class="na">hostname</span><span class="pi">:</span> <span class="s2">"</span><span class="s">gitlab.example.com"</span>
<span class="err"> </span><span class="na">environment</span><span class="pi">:</span>
<span class="err"> </span><span class="na">GITLAB_OMNIBUS_CONFIG</span><span class="pi">:</span> <span class="pi">|</span>
<span class="err"> </span><span class="s"> external_url = "gitlab.example.com"</span>
<span class="err"> </span><span class="s"> ports:</span>
<span class="err"> </span><span class="s"> - "80:80"</span>
<span class="err"> </span><span class="s"> - "443:443"</span>
<span class="err"> </span><span class="s"> - "22:22"</span>
<span class="err"> </span><span class="s"> volumes:</span>
<span class="err"> </span><span class="s"> - "/srv/gitlab/config:/etc/gitlab"</span>
<span class="err"> </span><span class="s"> - "/srv/gitlab/logs:/var/log/gitlab"</span>
<span class="err"> </span><span class="s"> - "/srv/gitlab/data:/var/opt/gitlab"</span>
</code></pre></div></div>
<h3 id="1-5-docker-compose-실행">1-5. docker-compose 실행</h3>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose up <span class="nt">-d</span> <span class="c"># 백그라운드로 실행</span>
...
docker ps <span class="c"># 컨테이너 정상 구동 확인</span>
<span class="c"># +) 각 서비스 버전 업데이트</span>
docker-compose pull <span class="o">[</span>service...] <span class="c"># update</span>
docker-compose up <span class="nt">-d</span> <span class="o">[</span>service...] <span class="c"># 재실행</span>
</code></pre></div></div>
<h3 id="1-6-jenkins--gitlab-접속">1-6. Jenkins & GitLab 접속</h3>
<p>아래와 같은 화면이 보이면 설치 성공!</p>
<ul>
<li>Jenkins 접속 : <a href="http://localhost:8080">http://localhost:8080</a></li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/jenkins-main.png" alt="jenkins-main" /></p>
<ul>
<li>gitlab 접속 : <a href="http://localhost:80">http://localhost:80</a></li>
</ul>
<p><img src="/assets/images/usingimages/jenkins_tutorial/gitlab-main.png" alt="gitlab-main" /></p>
<h2 id="마무리">마무리</h2>
<p>docker-compose를 이용해 간편하게 Jenkins와 GitLab을 설치하고 실행시켜 보았습니다. <br />
다음 시간에는 Jenkins, GitLab login 및 기본적인 Jenkins Setting에 대해 진행하겠습니다. <br />
감사합니다.</p>sungjun도커 컴포즈를 이용해 젠킨스, 깃랩 설치하기Gradle Multi Module Project 구성하기2019-04-03T00:00:00+00:002019-04-03T00:00:00+00:00https://gwonsungjun.github.io/articles/2019-04/gradle_multi_module<p>Gradle Multi Module Project 구성 방법을 알아보자</p>
<hr />
<h2 id="환경">환경</h2>
<p>spring boot 버전별로 설정 시 약간의 차이가 있으므로 주의.</p>
<ul>
<li>spring boot 2.1.3 (2019.04.03 기준 최신 버전)</li>
<li>gradle 4.10.3</li>
<li>jdk 1.8</li>
<li>intellij</li>
</ul>
<h2 id="1-create-root-project">1. Create Root Project</h2>
<ul>
<li>(1) New Project > Gradle > Additional Libraries and Frameworks > java 선택 > Next</li>
<li>(2) GroupId, ArtifactId 입력 > Next</li>
<li>(3) Use auto-import 체크 해제되어있는지 확인 > Next > Finish</li>
</ul>
<h2 id="2-create-sub-project">2. Create Sub Project</h2>
<p>필요한 서브 프로젝트 개수만큼 생성</p>
<ul>
<li>(1) File > New > Module</li>
<li>(2) Gradle > Additional Libraries and Frameworks > java 선택 > Next</li>
<li>(3) Group, Version Inherit 체크 되어있는지 확인</li>
<li>(4) ArtifactId 입력 > Next</li>
<li>(5) Sub Project는 Root Project 바로 아래에 모듈이 생성되어야 함. Content root 경로 잘 확인하기 > Finish</li>
</ul>
<h2 id="3-project-기본-골격">3. Project 기본 골격</h2>
<ul>
<li>프로젝트 루트 밑에 src 폴더가 생성되었다면 Delete</li>
<li>빌드는 항상 root 프로젝트를 기준으로 할 것이기 때문에 sub project의 gradle 폴더, gradlew, gradlew.bat, settings.gradle 등의 파일은 필요 없다. src 폴더와 build.gradle만 존재하도록 한다.
<ul>
<li>서브 프로젝트를 Gradle project로 생성하였다면 build.gradle만 존재하지만 spring Initializr로 생성하면 gradle 폴더, gradlew 등이 존재.</li>
</ul>
</li>
<li>Project 기본 골격은 아래 그림과 같다. (admin, api, common 서브 프로젝트 생성)</li>
</ul>
<p><img src="/assets/images/usingimages/gradle-multi-module/gradle-multi-module-scaffolding.png" alt="gradle-multi-module-scaffolding" /></p>
<h2 id="4-root-project와-sub-project-관계-설정">4. Root Project와 Sub Project 관계 설정</h2>
<ul>
<li>(자동으로 등록되어 있지 않다면) Root Project의 settings.gradle에 아래와 같은 형식으로 sub project name을 include.</li>
<li>sample-multi-module 프로젝트가 하위 프로젝트들을 관리하겠다는 의미.</li>
</ul>
<div class="language-gradle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rootProject</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="s1">'sample-multi-module'</span>
<span class="n">include</span> <span class="s1">'sample-api'</span>
<span class="n">include</span> <span class="s1">'sample-admin'</span>
<span class="n">include</span> <span class="s1">'sample-common'</span>
</code></pre></div></div>
<h2 id="5-root-buildgradle-수정">5. Root build.gradle 수정</h2>
<div class="language-gradle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">buildscript</span> <span class="o">{</span>
<span class="n">ext</span> <span class="o">{</span>
<span class="n">springBootVersion</span> <span class="o">=</span> <span class="s1">'2.1.3.RELEASE'</span>
<span class="o">}</span>
<span class="k">repositories</span> <span class="o">{</span>
<span class="n">mavenCentral</span><span class="o">()</span>
<span class="o">}</span>
<span class="k">dependencies</span> <span class="o">{</span>
<span class="n">classpath</span><span class="o">(</span><span class="s2">"org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"</span><span class="o">)</span>
<span class="n">classpath</span> <span class="s2">"io.spring.gradle:dependency-management-plugin:1.0.6.RELEASE"</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="k">allprojects</span> <span class="o">{</span>
<span class="n">group</span> <span class="s1">'com.sungjun'</span>
<span class="n">version</span> <span class="s1">'1.0-SNAPSHOT'</span>
<span class="o">}</span>
<span class="k">subprojects</span> <span class="o">{</span>
<span class="n">apply</span> <span class="nl">plugin:</span> <span class="s1">'java'</span>
<span class="n">apply</span> <span class="nl">plugin:</span> <span class="s1">'org.springframework.boot'</span>
<span class="n">apply</span> <span class="nl">plugin:</span> <span class="s1">'io.spring.dependency-management'</span>
<span class="n">sourceCompatibility</span> <span class="o">=</span> <span class="mf">1.8</span>
<span class="k">repositories</span> <span class="o">{</span>
<span class="n">mavenCentral</span><span class="o">()</span>
<span class="o">}</span>
<span class="k">dependencies</span> <span class="o">{</span>
<span class="n">testCompile</span> <span class="nl">group:</span> <span class="s1">'junit'</span><span class="o">,</span> <span class="nl">name:</span> <span class="s1">'junit'</span><span class="o">,</span> <span class="nl">version:</span> <span class="s1">'4.12'</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="n">project</span><span class="o">(</span><span class="s1">':sample-api'</span><span class="o">)</span> <span class="o">{</span>
<span class="k">dependencies</span> <span class="o">{</span>
<span class="n">compile</span> <span class="nf">project</span><span class="o">(</span><span class="s1">':sample-common'</span><span class="o">)</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="n">project</span><span class="o">(</span><span class="s1">':sample-admin'</span><span class="o">)</span> <span class="o">{</span>
<span class="k">dependencies</span> <span class="o">{</span>
<span class="n">compile</span> <span class="nf">project</span><span class="o">(</span><span class="s1">':sample-common'</span><span class="o">)</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="6-각-sub-프로젝트의-buildgradle-수정">6. 각 Sub 프로젝트의 build.gradle 수정</h2>
<ul>
<li><a href="https://github.com/gwonsungjun/gradle-multi-module/blob/master/sample-api/build.gradle">각 프로젝트 별</a> 필요한 dependencies만 설정하면 된다.</li>
</ul>
<div class="language-gradle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">dependencies</span> <span class="o">{</span>
<span class="n">compile</span><span class="o">(</span><span class="s1">'org.springframework.boot:spring-boot-starter-web'</span><span class="o">)</span>
<span class="n">testCompile</span><span class="o">(</span><span class="s1">'org.springframework.boot:spring-boot-starter-test'</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="7-common-프로젝트-buildgradle-설정">7. common 프로젝트 build.gradle 설정</h2>
<ul>
<li>예제 project » <a href="https://github.com/gwonsungjun/gradle-multi-module">깃헙</a> 확인</li>
<li>위의 예제 project의 Common 프로젝트처럼 main 메소드가 없는 경우
<ul>
<li>아래와 같이 bootJar, jar enabled 설정을 해야한다.</li>
</ul>
</li>
</ul>
<div class="language-gradle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">bootJar</span> <span class="o">{</span>
<span class="n">enabled</span> <span class="o">=</span> <span class="kc">false</span>
<span class="o">}</span>
<span class="n">jar</span> <span class="o">{</span>
<span class="n">enabled</span> <span class="o">=</span> <span class="kc">true</span>
<span class="o">}</span>
<span class="k">dependencies</span> <span class="o">{</span>
<span class="n">compile</span><span class="o">(</span><span class="s1">'org.springframework.boot:spring-boot-starter-data-jpa'</span><span class="o">)</span>
<span class="n">runtime</span><span class="o">(</span><span class="s1">'com.h2database:h2'</span><span class="o">)</span>
<span class="n">testCompile</span><span class="o">(</span><span class="s1">'org.springframework.boot:spring-boot-starter-test'</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="8-다른-project에서-common-project를-사용-할-경우">8. 다른 Project에서 common project를 사용 할 경우</h2>
<p>다른 project에서 common project의 Entity 클래스와 Repsoitory를 사용하기 위해서는 <code class="language-plaintext highlighter-rouge">@EntityScan("com.sungjun.*")</code>, <code class="language-plaintext highlighter-rouge">@EnableJpaRepositories("com.sungjun.*")</code> 2개의 어노테이션을 설정해 줘야 한다. (Common Project에 Entity 클래스와 Repository만 있는 경우에 한하여)</p>
<ul>
<li><a href="https://github.com/gwonsungjun/gradle-multi-module/blob/master/sample-api/src/main/java/com/sungjun/api/SampleApiApplication.java">예제 project의 API Module SampleApiApplication class</a> 참조</li>
</ul>
<h2 id="마무리">마무리</h2>
<ul>
<li>위와 같이 그래들 멀티 모듈 기본 설정이 완료되면 실제 개발을 하는 데 큰 문제가 없을 것이다.</li>
<li>방법만 제시하고 각각의 상세한 설명은 생략하였는데 <a href="https://jojoldu.tistory.com/123">Gradle 멀티 프로젝트(모듈) 관리</a> 글과 같이 보면 이해가 조금 쉬울 것이다.(예제 프로젝트도 해당 블로그를 참고해서 작성하였다.)</li>
</ul>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://jojoldu.tistory.com/123">Gradle 멀티 프로젝트(모듈) 관리</a></li>
<li><a href="https://github.com/hantomato/gradle-multi-proj">gradle로 멀티 프로젝트 구성하기</a></li>
<li><a href="https://yookeun.github.io/java/2017/10/07/gradle-multi/">Gradle 에서 Multi 프로젝트 만들기</a></li>
</ul>sungjunGradle Multi Module Project 구성 방법을 알아보자2018년 회고2018-12-31T00:00:00+00:002018-12-31T00:00:00+00:00https://gwonsungjun.github.io/articles/2018-12/2018Review<p>2018년 한 해를 되돌아본다</p>
<hr />
<h1 id="2018년-회고">2018년 회고</h1>
<p>올해 1월 “이번 해 만큼은 뒤돌아봤을 때 후회 없을 만큼 최선을 다하자” 다짐하고 시작했는데 만족할 만큼은 아니지만 나름 부지런하게 보냈던 한해였던 것 같아 감히 처음으로 회고를 작성해본다.</p>
<ul>
<li>올해 나는 무엇을 하고 보냈을까? 뒤돌아보니 크게 아래와 같이 나눌 수 있었다.</li>
</ul>
<ol>
<li><a href="#1">회사</a></li>
<li><a href="#2">TIL / 블로그 / 1일 1커밋</a></li>
<li><a href="#3">주간회고</a></li>
<li><a href="#4">세미나 / 컨퍼런스</a></li>
<li><a href="#5">Study</a></li>
<li><a href="#6">무엇을 공부했나?</a></li>
<li><a href="#7">아쉬웠던 점</a></li>
<li><a href="#8">2019년 목표</a></li>
</ol>
<h2 id="1-회사-">1. 회사 <a id="1"></a></h2>
<p>2017년 9월에 입사를 했고 6개월 뒤인 2018년 3월 팀원 4명 중 2분이 퇴사하였다. 입사한 지 얼마나 됐다고..? <br />
처음에는 나도 그만둬야 하나 정말 많은 고민을 했었다. 사수의 부재로 내가 많은 것을 배우지 못하리라 생각했었다. <br />
많은 고민을 한 끝에 일단 해보고 아니다 싶으면 그때 돼서 다시 생각해보기로 결정을 내렸다. <br />
새로운 자리에서 일이 시작되면서 알아야 할 것이 기하급수적으로 증가하기 시작했고 혹여나 해결하지 못 하는 일이 생길까봐 두려워하기도 했었다. 특히, 이때부터 이제 믿을 건 나 자신밖에 없다는 생각으로 알게 된 내용을 에버노트에 하나씩 기록해 나가기 시작했고, 이게 쌓이고 쌓여 이제는 웬만한 업무 관련 지식은 에버노트 검색으로 다 찾을 수 있게 되었다. (현재는 이것을 정리해서 사내 위키로 옮기는 작업을 진행 중이다.)</p>
<h3 id="그래서-무슨-일을-해봤나">그래서 무슨 일을 해봤나?</h3>
<ul>
<li>기존 사내 프로젝트 운영 및 레거시 코드 개선
<ul>
<li>Admin 사이트, Batch, API Server</li>
</ul>
</li>
<li>로그 모니터링, 트러블 슈팅, 서버 운영, 소스 관리, 배포</li>
<li>DevOps 도입을 위해 연구 및 테스트 진행
<ul>
<li>Jenkins, Docker, ELK Stack</li>
</ul>
</li>
<li>최신 기술 서칭 및 테스트 프로젝트 진행
<ul>
<li>특히, 블록체인을 집중적으로 (Geth)</li>
</ul>
</li>
<li>외부 프로젝트 API Server 개발
<ul>
<li>Springboot, JPA, Gradle …</li>
</ul>
</li>
<li>팀 내 Wiki 사이트 구축</li>
</ul>
<p>주 업무는 기존 서비스의 유지보수 였고 이를 통해 서비스 운영에 있어 적잖은 노하우를 쌓게 되었다. 아쉬운 점이라면 개발과 운영의 비중이 내가 바라는 바와는 조금 달랐다는 것이다. 이외에도 GitLab, Trello, Slack 도입 및 적극 사용으로 조금 더 좋은 환경에서 개발할 수 있도록 노력하기도 했었다.</p>
<h2 id="2-블로그--til--1일-1커밋-">2. 블로그 / TIL / 1일 1커밋 <a id="2"></a></h2>
<ul>
<li>Jekyll을 이용해서 깃헙 블로그를 생성하였다. 기존 테마에서 조금 커스터마이징해서 나름 깔끔한 모습으로 사용 중이다.</li>
</ul>
<p><img src="/assets/images/usingimages/2018Review/2018Review_blog.png" alt="2018Review_blog" /></p>
<ul>
<li>블로그 생성 당시에는 기술 관련 글을 작성하려고 시작했는데 현재는 주간회고의 글로 가득 차 있다.</li>
<li>대부분의 개발 관련 지식을 <a href="https://github.com/gwonsungjun/TIL">GitHub TIL Repository</a>에 작성하였고 이게 지속되다보니 블로그는 주간회고, TIL은 개발 관련 내용으로 나눠 사용하게 되었다. 블로그에 주간회고만 작성하기에는 아깝다고 생각되어 내년에는 조금씩 기술 글을 작성해 나갈 생각이다.</li>
</ul>
<p><img src="/assets/images/usingimages/2018Review/2018Review_TIL.png" alt="2018Review_TIL" /></p>
<ul>
<li>1일 1커밋도 도전해봤었다. 1일 1커밋에 대한 이런저런 얘기가 많지만, 개인적으로는 도움이 되었다. 물론 처음에는 너무 깃 그래프에만 신경을 써서 잘못된 방향으로 흘러갈 뻔했지만 무조건 커밋을 해야 된다는 생각을 버리고 그날 배운걸 정리할 수 있으면 최대한 정리해서 커밋하자는 생각으로 하니 나름 만족도가 높았다.</li>
</ul>
<p><img src="/assets/images/usingimages/2018Review/2018Review_GitGraph.png" alt="2018Review_GitGraph" /></p>
<ul>
<li>이러한 꾸준함 덕분인지 개발자라면 다 아는 HR 컨설팅 회사로부터 연락을 받게 되었고 계속 인연을 이어 나가고 있다. 나에게도 이런 행운이 찾아올 줄은 예상도 못 했다.</li>
</ul>
<h2 id="3-주간회고-">3. 주간회고 <a id="3"></a></h2>
<p><a href="http://blog.devjoshua.me/">Joshua</a> 님의 블로그를 접하고 처음 시작하게 된 주간 회고. 처음에는 그냥 한번 해보자는 생각으로 시작했는데 1년 동안 한 주도 빠짐없이 꾸준히 작성하게 되었다.
하나둘 쌓여 주간 회고 포스트만 무려 49개가 되었고 최근에는 <a href="https://www.facebook.com/devbeginner/?__tn__=kC-R&eid=ARDLB37dwQ0Gp8vw4nUddINv1xI8gA6wd679BUCybaze_epi0EVibA639er33OycA-RbExrg-Lh3sxCt&hc_ref=ARSykpAPmOIpuYRiJ217Abcx3KsWuAWAXEYJzeJ-3RcSHM2qRTXsOhQwStmAA_I0my0&fref=nf&__xts__[0]=68.ARCKEnnV5WIS5q7J4MpRjKSDkbHq6mIecbXmS66B5dUchHZqbDisNq0V8Gwn_gmHP7tNiFA8FobTAP5sZGRUEG4z3SsOnuC7ffhpbd8_PERJlWeI8qBXO2qeqXsmDSn8PBgSPk26sm2cQY-R7dIRKoUh2egu51JS79tZ0Mf1DkXYLRniHc4kuTXBTZDcuiwMAjvyGNdyXIi_qsP_p_A7lTVnuA6RxDSdm64pu0hhrgzLUB0GEZTwgLo8vjpwG0cnHvCDCCwrJEut_HeBN8RA83ZBRfI82nu-OkEsR3XrJA7IGRW0z935-Gnr1zwpLZUqqilwYdpsrMnSLuJredUjLk2yj_PMc1_jZGq7ZSYoTQysOiD8DFvebQ8">Facebook 초보 개발자 모임</a>에 소개가 되었다. 처음 공개 되었을 때 조금 부끄러운 마음도 있었지만 직접 찾아서 읽어봐 줬다는 것에 너무 감사했다.</p>
<p><img src="/assets/images/usingimages/2018Review/2018Review_facebook.jpeg" alt="2018Review_facebook" /></p>
<h3 id="주간회고를-작성하며-느낀-점">주간회고를 작성하며 느낀 점</h3>
<ul>
<li>글쓰기 능력이라 하면 아직 턱없이 부족하지만, 글을 요약하는 능력은 전보다 많이 좋아졌다고 느꼈다. 특히 회사 메일을 쓸 때 많이 느꼈다.</li>
<li>매주 스스로 성찰할 수 있는 시간을 가지게 되었다.
<ul>
<li><a href="https://mindscale.kr/course/how-to-learn-prg">프로그래밍, 어떻게 공부할 것인가</a>, <a href="https://www.youtube.com/watch?v=Xcy2Pq6LABk&feature=youtu.be">프로그래밍 학습 방법 </a>, <a href="http://woowabros.github.io/experience/2017/12/11/how-to-study.html">학습에 실패한 이야기</a>에서 설명하는 의식적인 연습 “집중하고 고치고 반복하기” 즉, 지속적인 피드백을 주간회고를 통해 어느 정도 실천을 할 수 있었지 않았나 싶다.</li>
</ul>
</li>
<li>출퇴근길에 읽었던 블로그들을 매주 정리했는데 이게 아주 도움이 된다. 사람은 망각의 동물이라고 특히 책이 아닌 블로그는 일회성 글로 좋은 글이라도 쉽게 잊어버리는 것 같았다. 그래서 괜찮았던 블로그들을 아카이빙 할 수 있는 방법으로 블로그를 읽고 요약해서 정리해놓았다.</li>
<li>시간이 지나 같은 블로그를 또 한 번 접했을 때 언제 한번 읽어 봤던 것 같은데? 라는 생각이 들면 블로그의 검색 기능을 이용해서 해당 블로그를 찾고 또 한 번 읽을 필요 없이 요약한 내용으로 쉽게 파악할 수 있었다.
<ul>
<li>전날 저녁 그리고 당일 아침에 읽은 블로그들을 <a href="https://www.pushbullet.com/">pushbullet</a> 으로 옮기고 출근을 조금 일찍 해서 pushbullet에 옮겨진 블로그들을 에버노트에 정리 요약을 해놓는다. 그리고 주간회고를 작성하는 일요일에는 에버노트에 정리된 내용을 덮어씌우기만 하면 되었다.</li>
</ul>
</li>
</ul>
<h2 id="4-세미나--컨퍼런스-">4. 세미나 / 컨퍼런스 <a id="4"></a></h2>
<p>올해 목표는 한 달에 한 번 이상 세미나 및 컨퍼런스에 참석하는 것이었다. 한 달에 한 번이면 그렇게 많다고 생각이 들지 않아서 잡은 목표였는데 12월 한 달 빼고는 모두 다녀왔다. <br />
다녀온 세미나 / 컨퍼런스 / Hands-on은 아래 목록과 같다.</p>
<h3 id="community-activities">Community Activities</h3>
<ul>
<li>2018.11.10 <a href="http://www.ksug.org/seminar/20181110/">KSUG 스프링 기반 REST API 개발 - 백기선님의 특별강연</a></li>
<li>2018.10.18 <a href="http://www.okkycon.com/">OKKYCON:2018 - The Real TDD</a></li>
<li>2018.10.11 <a href="https://deview.kr/2018/pick/6731">Deview 2018</a></li>
<li>2018.09.04 <a href="https://if.kakao.com/">if Kakao 개발자 컨퍼런스</a></li>
<li>2018.08.31 <a href="https://festa.io/events/70">Popit 멘토링 데이</a></li>
<li>2018.07.28 <a href="https://festa.io/events/45">하시코프 한국 사용자 밋업(HashiCorp Korea User Group MeetUp)</a></li>
<li>2018.06.27 <a href="https://gwonsungjun.github.io/seminar/2018/06/27/codesquadSeminar/#">제 5회 마스터즈 오픈 세미나, 코드 스쿼드</a></li>
<li>2018.06.21 <a href="https://gwonsungjun.github.io/seminar/2018/06/25/okkyTddSeminar/#">OKKY, TDD 잘알못을 위한 돌직구 세미나</a></li>
<li>2018.06.10 Google I/O Extended 2018 Seoul</li>
<li>2018.05.19 <a href="https://gwonsungjun.github.io/seminar/2018/05/20/6th_oracle_kafka/">Oracle Developer Meetup - Understanding Kafka</a></li>
<li>2018.04.28 <a href="https://gwonsungjun.github.io/seminar/2018/04/29/ubuntuRelaseParty/">Ubuntu 18.04 Release Party in Seoul</a></li>
<li>2018.04.21 <a href="https://gwonsungjun.github.io/seminar/2018/04/22/springCamp2018/">SPRING CAMP 2018 (with Coupang)</a></li>
<li>2018.04.13 <a href="https://gwonsungjun.github.io/seminar/2018/04/15/9xd11meeting/">9XD: Young, Wild Coders - Hello! New Face; The eleventh meeting</a></li>
<li>2018.03.18 <a href="https://gwonsungjun.github.io/seminar/2018/03/22/4th_oracle_meetup/">Oracle Developer Meetup - Future Java and the Microservice in Your Hands!</a></li>
<li>2018.02.11 <a href="https://gwonsungjun.github.io/seminar/2018/02/22/GdgCampusKoreaMeetup/">GDG Campus 2018 Meetup</a></li>
<li>2018.01.27 <a href="https://gwonsungjun.github.io/seminar/2018/01/27/3rd_oracle_meetup/">Oracle Developer Meetup - Serverless Computing</a></li>
</ul>
<h3 id="hands-on">Hands-On</h3>
<ul>
<li>2018.07.14 AWSKRUG Hands-on Lab 2018 : Container #3, Kubernetes on AWS</li>
<li>2018.06.30 AWSKRUG Hands-on Lab 2018 : Serverless #1, 손쉽게 시작하는 Serverless Architecture</li>
<li>2018.06.16 AWSKRUG Hands-on Lab 2018 : Container #2, 아마존 ECS에 자바 마이크로 서비스 구축하기</li>
<li>2018.06.02 <a href="https://gwonsungjun.github.io/seminar/2018/06/02/awsDocker/">AWSKRUG Hands-on Lab 2018 : Container #1 - Docker</a></li>
</ul>
<h3 id="느낀-점">느낀 점</h3>
<ul>
<li>많이 참석했을 수도 있고 아닐 수도 있다. 생각 없이 그저 가면 좋다니깐 간 건 아니다. 목적은 회사 내에 정체되어있기 싫어서였다. 최대한 직접 나가서 최신 동향이나 키워드를 파악하고 싶었다. 그리고 배워온 것을 직접 써보고 익혀보고 좋다고 생각이 들면 사내에 전파하고 싶은 마음이었다.</li>
<li>여러 개발자분을 만나서 얘기도 나누고 이런저런 활동을 하다 보니 재미도 있었고 한두 개씩 듣다 보니 시야가 조금씩 넓어지고 있다는 것도 느꼈다.</li>
<li>한가지 간과해서는 안 되는 건 발표를 들었다 해서 그것을 내가 아는 것이 아니라는 것이다. 키워드만 알게 된 것이다. 들은 내용을 바탕으로 직접 학습하고 익혀야 내 것이 될 수 있다는 것을 느꼈다.</li>
<li>그리고 나는 백엔드 기술에 관심이 많아서 프론트 관련 발표는 흥미가 없다는 것을 알게 되었다. 여러 분야의 지식들을 들어 놓으면 도움은 되겠지만, 당장은 귀에 들어오지 않아 당분간은 백엔드 관련 세미나에만 참석할 생각이다.</li>
</ul>
<h2 id="5-study-">5. Study <a id="5"></a></h2>
<p>올해는 총 3개의 스터디를 진행하였는데 2개는 성공적이었고 하나는 조금 흐지부지하게 끝났다. 독서 모임도 잠깐 했었다.</p>
<h4 id="알고리즘-스터디">알고리즘 스터디</h4>
<ul>
<li>알고리즘에 대해 감을 잡고 싶어 시작하게 되었다. 처음에는 <a href="https://book.naver.com/bookdb/book_detail.nhn?bid=7058764">알고리즘 문제 해결 전략</a> 책으로 시작했는데 입문하기에는 조금 어려운 감이 있어서 <a href="https://www.codility.com/">Codility</a>에서 문제 풀고 공유하는 시간을 가지기로 중간에 변경하기도 했다. 4명에서 진행했는데 2분이 스터디 도중 이직 성공으로 하차 하셔서 흐지부지하게 끝났다.</li>
</ul>
<h4 id="자바카페-커뮤니티-스프링5-레시피-스터디"><a href="https://www.facebook.com/groups/javacafe/?ref=br_rs">자바카페 커뮤니티</a> 스프링5 레시피 스터디</h4>
<ul>
<li>자바카페 커뮤니티는 오래전부터 스터디를 계속 진행해오던 터라 운영 방식이나 규칙들이 너무 잘 갖춰져 있었다. 스터디 당일 발표자를 랜덤으로 뽑아 진행했기 때문에 항상 발표를 한다는 마음으로 평소보다 더 깊게 공부할 수 있었다. 올해 진행했던 스터디 중에서 가장 만족하고 스프링을 다시 한번 공부할 수 있었던 좋은 기회였다.</li>
</ul>
<h4 id="스프링-부트-스터디">스프링 부트 스터디</h4>
<ul>
<li>스프링을 조금 공부해봤으니 스프링부트도 학습을 해봐야겠다고 생각하던 찰나에 Facebook 친구인 대희님께서 스프링부트 스터디원을 모집하고 있었다. 잘됬다 싶어 스터디 신청을 하였고 약 1달 반 정도 스터디를 진행하였다. 첫 모임을 제외하고 모두 온라인(행아웃)으로 진행하였는데 오프라인과 온라인 각각이 장단점이 있겠지만 개인적으로 온라인 스터디도 매우 만족스러운 방식이었다.</li>
</ul>
<h4 id="트레바리-독서-모임-보통의-존재-1809-시즌"><a href="https://trevari.co.kr/">트레바리 독서 모임</a> 보통의 존재 1809 시즌</h4>
<ul>
<li>1회 참여하고 2회 때 개인적인 사정으로 참석을 못 했는데 그때부터 의욕이 확 떨어져서 중간에 포기하였다. 분명 끝까지 했으면 도움이 되긴 했을 텐데 다음에 시간적으로 여유로울 때 꼭 신청을 해볼 것이다.</li>
</ul>
<h2 id="6-무엇을-공부했나-">6. 무엇을 공부했나? <a id="6"></a></h2>
<ul>
<li>올해 상반기에는 기초부터 잡자는 생각에 Servlet부터 다시 공부했었다.</li>
<li>Servlet 공부를 마친 후에는 실제로 당장 개발하는데 필요한 Spring이 부족하다는 것을 느껴 Spring 위주의 학습을 했었다.</li>
<li>따지고 보면 주로 Java, Spring, JPA 위주의 학습이었다.</li>
<li>강의를 들을 때는 인프런을 적극적으로 활용해서 들었고 여러 기술의 이해를 도와주었다.</li>
<li>아래 읽은 책 목록들은 꼭 완독하지는 않았다. 필요한 부분을 찾아 읽으려고 노력했다.</li>
<li>책을 읽고 느낀 점이나 생각들은 주간회고나 TIL에 작성이 되어있어서 필요하면 검색해서 참고해도 좋을 듯하다.</li>
</ul>
<h3 id="읽은-책-목록">읽은 책 목록</h3>
<ul>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=5902081">Head First Servlets & JSP</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=7317474">코딩을 지탱하는 기술</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=13316548">블록체인 무엇인가?</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=9685493">비트코인, 블록체인과 금융의 혁신</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=9738902">SQL 첫걸음</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=7058764">알고리즘 문제 해결 전략</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=11823284">Hello Coding 그림으로 개념을 이해하는 알고리즘</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=10995037">만화로 배우는 리눅스 시스템 관리 1</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=4529127">Java 언어로 배우는 디자인 패턴 입문</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=4441100">자바 성능을 결정짓는 코딩 습관과 튜닝 이야기</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=8883567">Java 8 in Action</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=8920762">스프링 입문을 위한 자바 객체 지향의 원리와 이해</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=13911953">스프링5 레시피</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=14031681">처음 배우는 스프링 부트2</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=9252528">자바 ORM 표준 JPA 프로그래밍</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=12692342">프로그래밍의 정석</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=13256615">Do it! vue.js 입문</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=11091521">완벽한 it 인프라 구축을 위한 docker</a></li>
</ul>
<h3 id="들은-강의들">들은 강의들</h3>
<ul>
<li><a href="https://www.inflearn.com/course/intellij-guide/">IntelliJ를 시작하시는 분들을 위한 IntelliJ 가이드</a></li>
<li><a href="https://www.inflearn.com/course/spring/">백기선님의 스프링 프레임워크 입문</a></li>
<li><a href="https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/">백기선님의 스프링 부트 개념과 활용</a></li>
<li><a href="https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-jpa/">백기선님의 스프링 데이터 JPA</a></li>
<li><a href="https://www.inflearn.com/course/elk-%EC%8A%A4%ED%83%9D-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D/">ELK 스택 (ElasticSearch, Logstash, Kibana) 으로 데이터 분석</a></li>
<li><a href="https://www.inflearn.com/course/blockchain-%EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80-dapp/">블록체인 이더리움 부동산 댑(Dapp) 만들기 – 기본편</a></li>
</ul>
<h3 id="기타-서적">기타 서적</h3>
<ul>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=6332442">프로그래머의 길, 멘토에게 묻다</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=13318425">책 잘 읽는 방법</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=1877597">죽음의 수용소에서</a></li>
<li><a href="https://book.naver.com/bookdb/book_detail.nhn?bid=5186">데미안</a></li>
</ul>
<h3 id="내년에는-꼭-읽고-싶은-책들-이미-사놓은-책들">내년에는 꼭 읽고 싶은 책들 (이미 사놓은 책들)</h3>
<ul>
<li>Clean Code</li>
<li>켄트백의 구현 패턴</li>
<li>객체지향의 사실과 오해</li>
<li>클린 코더</li>
<li>리팩토링</li>
<li>이팩티브 자바</li>
<li>익스트림 프로그래밍</li>
<li>레거시 코드 활용 전략</li>
<li>읽기 좋은 코드가 좋은 코드다</li>
</ul>
<h2 id="7-아쉬웠던-점-">7. 아쉬웠던 점 <a id="7"></a></h2>
<ul>
<li>위에서 읽은 책 목록과 들은 강의들을 나열해보니 대부분의 시간을 Java, Spring 프레임워크에만 집중한 것 같아 아쉬웠다.</li>
<li>개인 프로젝트 (사이드 프로젝트)를 해보겠다고 했지만, 막상 제대로 한 게 없다. 계획만 새우고 항상 뒷전이었다.</li>
<li>집중력이 부족하다는 것을 느껴 뽀모도로 기법을 사용해야지 생각만 해놓고 실천을 못 했다. 조금 더 나은 퍼포먼스를 낼 수 있었을 것 같은데 아쉽다.</li>
<li>성장을 위해 나 자신을 너무 억압하지 않았나 싶다. 항상 최선을 다해서 열심히 하는 것도 좋지만 적당한 휴식과 여유도 필요함을 느꼈다.</li>
</ul>
<h2 id="8-2019년-목표-">8. 2019년 목표 <a id="8"></a></h2>
<ul>
<li>도구나 프레임워크 학습보다는 기본기에 더 집중하기 위해 노력하자.</li>
<li>운동 부족. 매일 아침 헬스장에 들려 운동을 하고 출근하자.</li>
<li>사이드 프로젝트 2개 이상을 꼭 진행해보자.</li>
<li>영어 공부를 게을리하지 않는다.</li>
<li>항상 “의도적 수련”을 실천하기 위해 노력한다.</li>
</ul>
<p>조금 추상적이긴 하지만 내년 목표 설정까지 마무리하였다. <br />
다사다난한 한 해가 지나가고 또다시 새로운 시작을 맞이한다. 이 글을 읽는 모든 분들 건강하고 행복한 새해가 되었으면 한다.</p>sungjun2018년 한 해를 되돌아본다Spring boot + LiveReload2018-08-30T00:00:00+00:002018-08-30T00:00:00+00:00https://gwonsungjun.github.io/articles/2018-08/springbootAutoreload<p>Intellij Spring boot 개발 시 자동 리로드 환경 구축</p>
<hr />
<h1 id="intro">Intro</h1>
<ul>
<li>Spring boot 개발 시 소스 변경이 일어날 때마다 매번 App을 재기동 시키는 일이 매우 번거로워 방법을 찾게 되었다.</li>
<li>크롬 확장 프로그램 <code class="language-plaintext highlighter-rouge">LiveReload</code>와 spring boot의 <code class="language-plaintext highlighter-rouge">devtools</code>를 이용하면 쉽게 자동 리로드 환경을 구축할 수 있다.</li>
<li>아래 설정 방법은 Chrome brower와 Intellij IDE를 기반으로 작성 하였다.</li>
</ul>
<h2 id="1-livereload-확장-프로그램-설치">1. LiveReload 확장 프로그램 설치</h2>
<p><img src="/assets/images/usingimages/liveReload/livereload1.PNG" alt="liveReload1" /></p>
<h2 id="2-의존성-추가">2. 의존성 추가</h2>
<ul>
<li>maven</li>
</ul>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><dependencies></span>
<span class="nt"><dependency></span>
<span class="nt"><groupId></span>org.springframework.boot<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>spring-boot-devtools<span class="nt"></artifactId></span>
<span class="nt"><optional></span>true<span class="nt"></optional></span>
<span class="nt"></dependency></span>
<span class="nt"></dependencies></span>
</code></pre></div></div>
<ul>
<li>Gradle</li>
</ul>
<div class="language-gradle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">dependencies</span> <span class="o">{</span>
<span class="n">compile</span><span class="o">(</span><span class="s2">"org.springframework.boot:spring-boot-devtools"</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="3-intellij-compiler-설정">3. Intellij Compiler 설정</h2>
<ul>
<li>Ctrl + Shift + A : compiler 입력</li>
<li><code class="language-plaintext highlighter-rouge">Build project automatically 체크</code>-> Apply</li>
</ul>
<p><img src="/assets/images/usingimages/liveReload/livereload2.PNG" alt="liveReload2" /></p>
<h2 id="4-intellij-registry-설정">4. Intellij registry 설정</h2>
<ul>
<li>Ctrl + Shift + A : registry 입력</li>
<li><code class="language-plaintext highlighter-rouge">compiler.automake.allow.when.app.running 체크</code> -> close</li>
</ul>
<p><img src="/assets/images/usingimages/liveReload/livereload3.PNG" alt="liveReload3" /></p>
<h2 id="추가-팁">추가 팁</h2>
<ul>
<li>default 설정이 아닌 커스텀해서 사용하고 싶은 경우 application.yml 파일에서 수정 가능.</li>
</ul>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">spring</span><span class="pi">:</span>
<span class="na">devtools</span><span class="pi">:</span>
<span class="na">restart</span><span class="pi">:</span>
<span class="na">enabled</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">livereload</span><span class="pi">:</span>
<span class="na">enabled</span><span class="pi">:</span> <span class="no">true</span>
</code></pre></div></div>
<h2 id="확인">확인</h2>
<ul>
<li>spring boot App을 실행하고 browser에서 LiveReload extension 클릭해서 활성화(Enable) 시켜주면 변경사항이 생길 시 자동으로 리로드 해주는 것을 확인할 수 있다.</li>
</ul>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://stackoverflow.com/questions/33869606/intellij-15-springboot-devtools-livereload-not-working">https://stackoverflow.com/questions/33869606/intellij-15-springboot-devtools-livereload-not-working</a></li>
<li><a href="http://haviyj.tistory.com/11">http://haviyj.tistory.com/11</a></li>
</ul>sungjunIntellij Spring boot 개발 시 자동 리로드 환경 구축