Jekyll2023-07-30T22:00:19+09:00https://kunhee.kim/feed.xmlㅋ_ㅋ블로그 이전 https://kukim.tistory.com🅺🆄🅺🅸🅼kunheeya@gmail.com맥북 발열과 한판 붙기 (feat. Macbook pro 16)2021-08-10T00:00:00+09:002021-08-12T18:50:00+09:00https://kunhee.kim/life/macbook-overheating-fix<p>블로그 글 이동 <a href="https://kukim.tistory.com/23">맥북 발열과 한판 붙기 (feat. Macbook pro 16)</a></p>
<h1 id="들어가며">들어가며</h1>
<p>애플은 디테일의 끝판왕이다. 대부분의 고객들은 애플의 UX에 헤어나오지 못한다.</p>
<p>예로 한 손에 들어오는 아이폰, 밀어서 잠금 해제는 혁신적이다.
이 혁신은 노트북에도 이어진다. 인텔 칩셋 기반 맥북은 뛰어난 노트북이다. 하지만 사실 난방기구다. 겨울철 무릎 위에 올리고 사용하면 자신도 모르게 그 따뜻함에 빠지게 된다. <del>팀쿡이 한국 온돌에 반해 맥북을 따뜻하게 개발했다는 설이있..</del><br />
아쉽게도 이 기능은 2021년 ARM 기반 칩셋 M1 맥북 이후 사라졌다. <del>킹받네</del></p>
<p>이 글은 2019년 맥북 프로 16인치 발열 탈출 성공기(경험담)입니다.</p>
<h1 id="-발열과-한판-붙기">🔥 발열과 한판 붙기</h1>
<p>인텔 맥북의 발열과 비행기 이륙은 유명합니다.<br />
하지만 제 맥북은 더이상 <del>난방기구</del>가 아닙니다.</p>
<ul>
<li>맥북과 연결된 주변 기기
<ul>
<li>24인치 QHD Dell 모니터 x 2대</li>
<li>USB : 화상캠, 스피커, sd 카드</li>
<li>랜선 연결</li>
<li>블루투스 : 키보드, 마우스</li>
</ul>
</li>
</ul>
<h2 id="before--after"><strong>Before & After</strong></h2>
<ul>
<li><strong>Before</strong>
<ul>
<li>평상시 : 70~80℃</li>
<li>풀 작업시 : 80~90℃</li>
</ul>
</li>
</ul>
<p>5가지 작업 후</p>
<ul>
<li><strong>After</strong>
<ul>
<li>평상시 : 40~50℃</li>
<li>풀 작업시 : 50~60℃**</li>
</ul>
</li>
</ul>
<blockquote>
<p>약 20~30℃ 발열 감소 🧊💻🧊 (실내 온도 26~28℃ 기준)</p>
</blockquote>
<h2 id="발열을-줄이기-위한-5가지-방법">발열을 줄이기 위한 5가지 방법</h2>
<ol>
<li>독(dock)(약 5℃ ⬇️ ) ⭐⭐</li>
<li>클렘쉘 모드(약 3℃ ⬇️ ) ⭐</li>
<li>공중부양(약 5℃ ⬇️ ) ⭐⭐</li>
<li>써멀패드(약 10℃ ⬇️ ) ⭐⭐⭐⭐</li>
<li>S/W 해결 (약 2~3℃ ⬇️ ) ⭐⭐</li>
</ol>
<hr />
<h1 id="1-독dock">1. 독(dock)</h1>
<p><strong>연결할 외부 기기가 많은 경우에만 해당함</strong></p>
<ul>
<li>요약 : 연결할 기기가 많은 상황에서 독(dock) 사용 후 약 <strong>5℃</strong> 떨어졌다.</li>
<li>발열 원인 : 자체 전력이 없는 허브는 맥북의 전력을 사용한다.
<ul>
<li>허브 - 맥북(usb-c) 연결 단자에 발열이 크다.</li>
<li>10만원짜리 허브가 있지만 이것도 발열을 잡지 못했다. <del>집에 있는 허브만 4개.. 쿨럭</del></li>
</ul>
</li>
<li>해결
<ul>
<li><strong>자체 전력이 있는</strong> 독을 사용한다.</li>
<li>연결할 모니터나 주변 기기가 많다면 자체 전력이 있는 독을 사길 바란다.</li>
</ul>
</li>
<li>제품 추천
<ul>
<li>벨킨 썬더볼트3 독 프로 or 익스프레스 독</li>
<li>caldigit ts3 plus</li>
<li><img src="https://www.caldigit.com/wp-content/uploads/2020/01/TS3-Plus-12A-1536x958.jpg" alt="caldigit" /></li>
<li>사진출처 : CalDigit 공식홈페이지</li>
<li>자체전력, Power가 따로 있다.</li>
</ul>
</li>
</ul>
<hr />
<h1 id="2-️-클램쉘-모드">2. 🧍♂️ 클램쉘 모드</h1>
<p><strong>외장모니터를 사용하는 경우에만 해당함</strong></p>
<ul>
<li>요약 : 클램쉘 모드 이후 약 <strong>3℃</strong> 떨어졌다.</li>
<li>발열 원인 : 내장 모니터 + 외장 모니터 사용시 맥북 GPU에 더 큰 부하가 간다.</li>
<li>해결
<ul>
<li>내장 모니터를 사용하지 않는다.</li>
</ul>
</li>
<li>해결의 단점
<ul>
<li>클램쉘 모드를 지속적으로 사용시 생기는 문제</li>
<li>Macbook Pro 로고가 있는 흰지 부분이 상당히 뜨겁다.</li>
<li>맥북 디스플레이에 지속적으로 뜨거운 부분이 닿으면 디스플레이에 문제가 있지 않을까하는 논란이다.</li>
</ul>
</li>
<li>해결의 단점의 해결 <del>(해단해)</del>
<ul>
<li>클램쉘 모드가 유지되는 지점(약 1cm) 열고 사용하면 디스플레이와 직접 닿는 문제를 약간 피하고 공기 순환된다.</li>
</ul>
</li>
</ul>
<p><img src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAxODEyMDFfMTMw%2FMDAxNTQzNjYyNzA5MDgx.HtTERWamxAmtHfXuwShkeMG5eA1gr3AdDdB6NXfBDzsg.n2KAXXb8-DC-2NE9719QX2TZwaugCb0egE5spebDmkMg.PNG.skokqk%2FScreen_Shot_2018-12-01_at_10.08.04_pm.png&type=sc960_832" alt="클렘쉘모드" /></p>
<ul>
<li>사진출처 : apple twelve south bookarc</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/129205173-7c3410d0-e12c-4493-b5e5-39ec1945104e.png" alt="클렘쉘모드1cm오픈" /></p>
<hr />
<h1 id="3-️-공중부양">3. ☁️ 공중부양</h1>
<ul>
<li>요약 : 맥북 하판을 바닥과 띄우면 약 <strong>5℃</strong> 떨어졌다.</li>
<li>발열 원인 : 맥북 하판은 뜨겁다. 바닥과 붙어 있으면 하판이 식지 않는다.</li>
<li>해결
<ul>
<li>노트북 하판과 바닥을 물리적으로 띄운다</li>
<li>하판-바닥 사이 공기가 순환되어 발열을 잡는다.</li>
</ul>
</li>
<li>제품 추천
<ul>
<li>지우개, 노트북 거치대, 쿨링패드 중 아무거나 상관 없음
<ul>
<li>저렴하게는 지우개, 이쁜 디자인은 노트북 거치대!</li>
<li>기능은 모두 비슷하다. (3~5℃ ⬇️ )(영상 4분 16초 참고)</li>
</ul>
</li>
<li>단, <strong>써멀패드 작업을 한다면 쿨링패드</strong>를 추천한다.</li>
</ul>
</li>
</ul>
<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">
<iframe src="https://www.youtube-nocookie.com/embed/B2zoGpny52k" frameborder="0" allowfullscreen=""></iframe>
</div>
<hr />
<h1 id="4-️-써멀패드">4. ❄️ 써멀패드</h1>
<ul>
<li>요약 : 맥북 VRM에 써멀패드 부착 후 약 <strong>10 ℃</strong> 떨어졌다.</li>
<li>발열 원인 : 맥북 발열의 주 된 원인은 고성능 CPU, GPU가 아닌 두 유닛에 전력을 공급하는 <strong>VRM</strong>(voltage regulator module)이다.</li>
<li>해결
<ul>
<li>맥북 하판을 분해하여 VRM에 써멀패드를 부착한다.</li>
<li>VRM 발열을 하판 알루미늄에 전도시켜 열을 분산한다.</li>
<li><strong>더욱 효과적으로 사용하려면 맥북 하판에 쿨링패드를 설치하여 하판 알루미늄을 식혀 발열을 잡아준다.</strong></li>
<li>써멀패드를 부착하며 펜에 쌓여있던 먼지도 함께 제거해주자.</li>
</ul>
</li>
<li>해결의 단점
<ul>
<li>하판 분해시 애플 공식 A/S 받기 어려울 수 있다.</li>
<li>써멀패드 부착 후 알루미늄 하판이 더 뜨겁다. (내 무릎은 소중하니까)</li>
<li>써멀패드에 닿는 하판 부분이 지속적인 열로 인해 변색될 수 있다. (지켜봐야할 문제)</li>
</ul>
</li>
</ul>
<h2 id="41-준비물">4.1 준비물</h2>
<ul>
<li>p5 드라이버
<ul>
<li><a href="[https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&query=샤오미+미지아+정밀+드라이버](https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&query=%EC%83%A4%EC%98%A4%EB%AF%B8+%EB%AF%B8%EC%A7%80%EC%95%84+%EC%A0%95%EB%B0%80+%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84)">샤오미 미지아 WIHA 정밀 드리아버 세트 구입 (19500원)</a></li>
</ul>
</li>
<li>써멀패드 1.5mm
<ul>
<li><a href="[https://search.shopping.naver.com/search/all?frm=NVSHATC&origQuery=써멀패드&pagingIndex=1&pagingSize=40&productSet=total&query=써멀패드&sort=review&timestamp=&viewType=list](https://search.shopping.naver.com/search/all?frm=NVSHATC&origQuery=%EC%8D%A8%EB%A9%80%ED%8C%A8%EB%93%9C&pagingIndex=1&pagingSize=40&productSet=total&query=%EC%8D%A8%EB%A9%80%ED%8C%A8%EB%93%9C&sort=review&timestamp=&viewType=list)">써멀패드 1.5mm (15000원)</a></li>
<li>Thermalright 서멀패드 오딧세이 1.5mm (85mm * 45mm) 1장으로 해결</li>
</ul>
</li>
<li>+) 기타 피크, 빨판, 가위</li>
<li>느긋함</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/129021733-fdeb4bd7-53f0-42a6-8fd0-40dcebf6101f.jpeg" alt="써멀패드_준비물" /></p>
<h2 id="42-써멀패드-부착-방법">4.2 써멀패드 부착 방법</h2>
<ul>
<li>아래 영상을 참고로 써멀패드 아이디어를 얻었습니다. (두 번 보세요)</li>
</ul>
<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">
<iframe src="https://www.youtube-nocookie.com/embed/FmfOFIjeR_I" frameborder="0" allowfullscreen=""></iframe>
</div>
<ol>
<li>드라이버를 사용하여 하단 케이스를 제거한다.<a href="https://ko.ifixit.com/Guide/MacBook+Pro+16-Inch+2019+%ED%95%98%EB%8B%A8+%EC%BC%80%EC%9D%B4%EC%8A%A4+%EA%B5%90%EC%B2%B4/135013">하단 케이스 제거 방법</a>
<ul>
<li><strong>하단 케이스 제거 방법 링크의 4,5단계 주의사항</strong>
<ul>
<li>틈새에 피크를 넣고 돌아가며 밀 때 피크가 배터리에 닿아 찢어져 터질 수 있다.</li>
<li>아래 사진을 보고 조심하도록 하자.. (쿨럭)</li>
<li><img src="https://user-images.githubusercontent.com/57086195/129022040-964231d5-89ce-4296-b01a-1b4f109c89dd.jpeg" alt="전체사진" /></li>
<li>
<p><img src="https://user-images.githubusercontent.com/57086195/129021747-3b421276-8969-4926-b3d3-1eb4551a30ed.jpeg" alt="써멀패드_배터리터짐" /></p>
</li>
<li><img src="https://user-images.githubusercontent.com/57086195/129021755-9886d8ec-3d32-4c27-bf2f-a0b44bebab3b.jpeg" alt="써멀패드_배터리2" /></li>
<li><img src="https://user-images.githubusercontent.com/57086195/129021757-f18f3e45-9010-4457-856e-ad25c33e74c0.jpeg" alt="써멀패드_배터리3" /></li>
<li>배터리가 찢어지고 스파크가 튀었다. 사설 수리 센터 문의 결과 테이프 부착 후 맥북 전원이 들어 온다면 문제가 없다고 하여 그냥 쓰기로 했다. <del>나중에 터지면 어쩌지…</del></li>
</ul>
</li>
</ul>
</li>
<li>써멀패드를 부착한다. (1번 영상 참고, 낮은 곳엔 3겹, 높은 곳엔 2겹)
<ul>
<li><img src="https://user-images.githubusercontent.com/57086195/129021759-42d4f5b8-f38d-4ebc-8715-b73d76970826.jpeg" alt="써멀패드_부착" /></li>
</ul>
</li>
<li>하판 케이스 복구 (2번 링크 마지막 단계 참고)</li>
<li>끝</li>
</ol>
<h2 id="43-써멀패드-테스트">4.3 써멀패드 테스트</h2>
<p>4k 영상을 10분간 두 모니터에 띄운 후</p>
<ul>
<li>독 + 클램쉘 모드 + 쿨링패드 : <strong>70 ~ 80</strong> <strong>℃</strong>
<ul>
<li><img src="https://user-images.githubusercontent.com/57086195/129021882-e1d61af8-af66-48ac-864d-1972ed1f97fd.png" alt="before" /></li>
</ul>
</li>
<li>독 + 클램쉘 모드 + 쿨링패드 + 써멀패드 : <strong>50 ~ 60 ℃</strong>
<ul>
<li><img src="https://user-images.githubusercontent.com/57086195/129021892-84d2c8eb-7569-4d21-b886-71a9d220928e.png" alt="after" /></li>
</ul>
</li>
</ul>
<h1 id="5-sw-해결-약-23-️-">5. S/W 해결 (약 2~3℃ ⬇️ )</h1>
<h2 id="51-turbo-boost-onoff">5.1 Turbo Boost On/Off</h2>
<ul>
<li>요약 : 터보 부스터를 끈다. 과부화 작업시 약 <strong>2~3℃</strong> 떨어진다.</li>
<li>발열 원인 : <a href="https://www.intel.co.kr/content/www/kr/ko/gaming/resources/turbo-boost.html">인텔 칩셋 터보 부스트 기술</a>이 실행될 때 CPU에 부하가 간다.</li>
<li>해결 : Turbo Boost 기능을 On/Off 하는 App을 사용한다.</li>
<li>해결의 단점
<ul>
<li>Turbo Boost 기능이 없다.</li>
</ul>
</li>
<li>제품 추천
<ul>
<li><a href="http://tbswitcher.rugarciap.com/">Turbo Boost Switcher App / 무료 버전</a>
<ul>
<li>무료 버전만으로도 Turbo Boost 기능을 손쉽게 끄고 킬 수 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="52-fan-control">5.2 Fan Control</h2>
<ul>
<li>요약 : 맥북 쿨링 펜을 강하게 튼다. 약 <strong>2~3℃</strong> 떨어진다.</li>
<li>발열 원인 : 맥북 쿨링 시스템은 내부 온도에 맞게 Auto로 작동한다.</li>
<li>해결 : Fan Control을 수동으로 변경하는 App을 사용한다.</li>
<li>해결의 단점 : 올웨이즈 비행기 타임(맥북 펜이 항상 풀이다.)</li>
<li>제품 추천
<ul>
<li><a href="https://crystalidea.com/macs-fan-control">Macs Fan Control App / 무료</a></li>
<li>좌측 펜은 CPU와 가깝기 때문에 CPU 온도에 맞춰 설정한다.
<ul>
<li><img src="https://user-images.githubusercontent.com/57086195/129121773-2857f294-ec7f-4b8d-afe9-7815a896253b.png" alt="좌측온도설정cpu" /></li>
<li>우측 펜은 GPU와 가깝기 때문에 GPU 온도에 맞춰 설정한다.</li>
<li><img src="https://user-images.githubusercontent.com/57086195/129121761-1dc7d2ad-fa44-42bf-9744-cd5eadd5418b.png" alt="우측온도설정gpu" /></li>
</ul>
</li>
<li>펜속도 옵션 : 40도 부터 속도 증가 / 70도 이상시 최대 속도
<ul>
<li>상단 메뉴바 아이콘을 통해 모니터링하기 쉽다. (좌측 : Turbo Boost / 우측 : Mac fac Control)</li>
<li><img src="https://user-images.githubusercontent.com/57086195/129121799-622c3029-f667-4cce-bae9-06c0e97093a5.png" alt="상단메뉴바" /></li>
</ul>
</li>
</ul>
</li>
</ul>
<hr />
<h1 id="마치며">마치며</h1>
<ul>
<li>써멀패드와 먼지 제거가 가장 효과가 좋았습니다.</li>
<li>애플의 마지막 난방기구로 n년까지 사용하고자 하는 마음을 담았습니다.</li>
<li>사실 ARM 맥북 사고싶습니다.</li>
<li>궁금한 점 댓글 남겨주세요.😄</li>
<li>
<p><img src="https://user-images.githubusercontent.com/57086195/129031198-daa6ef5e-fe68-44ff-b534-dd834ba6eba9.jpeg" alt="셋팅_mac" /></p>
</li>
<li>+) egpu(외장 크래픽카드)를 추가하여 발열을 더 낮출 수 있다는 제보가 있습니다.
<ul>
<li>가격이 비싸고 내장 그래픽을 사용하지 않는 단점이 있습니다.(출처 : <a href="https://www.facebook.com/groups/macbookusergroup/">페이스북 맥 쓰는 사람들</a>)</li>
</ul>
</li>
</ul>
<hr />
<h1 id="-reference">🔗 Reference</h1>
<ul>
<li><a href="https://youtu.be/FmfOFIjeR_I">Youtube VRM 발열 잡는 방법 (디테일한 방법)</a></li>
<li><a href="https://ko.ifixit.com/Guide/MacBook+Pro+16-Inch+2019+하단+케이스+교체/135013">하단 케이스를 제거 방법</a></li>
<li><a href="https://www.clien.net/service/board/cm_mac/15423526">맥북프로 16 VRM 써멀패드 부착, 발열잡고 성능까지!</a></li>
<li><a href="https://www.clien.net/service/board/use/16184753">Macbook Pro 16’ 써멀 패드로 발열 잡기 ~~</a></li>
<li><a href="https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&query=샤오미+미지아+정밀+드라이버">샤오미 미지아 WIHA 정밀 드리아버 세트 구입 (19500원)</a></li>
<li><a href="https://search.shopping.naver.com/search/all?frm=NVSHATC&origQuery=써멀패드&pagingIndex=1&pagingSize=40&productSet=total&query=써멀패드&sort=review&timestamp=&viewType=list">써멀패드 1.5mm (15000원)</a></li>
<li><a href="http://tbswitcher.rugarciap.com/">Turbo Boost Switcher App / 무료 버전</a></li>
<li><a href="https://crystalidea.com/macs-fan-control">Macs Fan Control App/ 무료</a></li>
</ul>🅺🆄🅺🅸🅼kunheeya@gmail.com발열 20~30도 낮추는 5가지 방법, 독, 클램쉘 모드, 쿨링패드, 써멀패드, S/W[42seoul] Ft_containers : C++ STL 컨테이너 구현2021-03-09T00:00:00+09:002021-03-09T21:10:00+09:00https://kunhee.kim/42seoul/project-42seoul-ft_containers<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/20">Ft_containers : C++ STL 컨테이너 구현</a></p>
<h1 id="-ft_containers">📚 ft_containers</h1>
<p>@42seoul : (2021.02.02 ~ 2020.03.09)</p>
<h2 id="-about">📖 About</h2>
<ul>
<li>이 프로젝트는 C++ STL 라이브러리의 몇 가지 Container를 이해하기 위해 직접 구현해봅니다. (In this project you will implement the various container types of the C++ standard template library.)</li>
<li>구현 사항
<ul>
<li>C++ 98을 따릅니다.</li>
<li>:white_check_mark: List</li>
<li>:white_check_mark: Vector</li>
<li>:white_check_mark: Map</li>
<li>:white_check_mark: Stack</li>
<li>:white_check_mark: Queue</li>
<li>:white_check_mark: 각각의 컨테이너에 맞는 iterator</li>
</ul>
</li>
</ul>
<h2 id="-review">📝 Review</h2>
<ul>
<li>STL의 컨테이너들을 직접 구현하면서 가장 큰 이점은 단순히 STL 함수 사용법을 아는 것을 넘어 <a href="https://github.com/microsoft/STL">microsoft/STL</a> 오픈소스를 따라갈 수 있었으며 실제 구현이 어떻게 되어있는지 확인할 수 있었다. 이는 앞으로 어떤 함수든 구현사항을 뜯어볼 수 있다는 생각에 두려움이 사라졌다.</li>
<li>각 컨테이너를 구현하기 위해 자료구조를 이론적으로만 아는 것이 아닌 실제로 구현하니 좀 더 와닿았다.
<ul>
<li>i.e. vector는 동적 배열로 배열 크기의 재할당을 사용자가 신경쓰지 않고 사용하는 매우 유용한 컨테이너, 자료구조이다. (Python의 List도 동적 배열이다) 기존 C, CPP에서 동적배열 자료구조를 사용하지 않고 할당한 배열 크기를 넘었을 때는 재할당 해야하는 번거로움을 벗어난다는 구현하는데 있어 동적 할당 된 배열의 크기를 증가할 때 마다 새롭게 동적 할당하여 추가하는 문제를 해결했다. 이때 재할당 크기를 얼마만큼 사이즈를 설정해야할까를 찾던 중 <code class="language-plaintext highlighter-rouge">Growth Factor</code>의 값을 설정하여 (STL 기준 2) 동적할당 한다는 구현 방식이 새로웠다.</li>
<li>i.e. Map 컨테이너를 구현할 때 STL은 Red-Black tree로 구현되어 있다. 실제로 나만의 Map을 구현할 때 처음에는 단순 Binary tree로 구현하였는 데 트리 불균형 문제로 검색하는 데 O(log n)을 지키지 못했다. 이를 해결하기 위해 AVL-Tree 자료구조로 구현하였고 Red-Black tree와 같은 평균과 최악의 경우 검색,삽입,삭제 모두 O(log n)으로 구현할 수 있었다.</li>
<li>컨테이너들의 시간, 공간 복잡도 개선해야 한다. 같은 기능이어도 .size()를 찍어보면 큰 차이가 발생했다.</li>
</ul>
</li>
</ul>
<hr />
<h2 id="-reference">🔗 Reference</h2>
<ul>
<li><a href="https://github.com/microsoft/STL">microsoft/stl</a></li>
<li><a href="http://cplusplus.com/reference/stl/">cplusplus-Containers</a></li>
<li><a href="https://cs.stmarys.ca/~porter/csc/ref/stl/headers.html">STL Headers</a></li>
<li><a href="https://accu.org/journals/overload/9/43/frogley_442/">An introduction to C++ Traits</a></li>
<li><a href="https://www.codesdope.com/course/data-structures-avl-trees/">avl-trees</a></li>
<li><a href="https://www.youtube.com/channel/UCHcG02L6TSS-StkSbqVy6Fg/playlists?view=50&sort=dd&shelf_id=2">코드없는 프로그래밍</a></li>
</ul>
<h2 id="-author">🧑🏻💻 Author</h2>
<p><a href="https://github.com/ku-kim">kukim</a></p>🅺🆄🅺🅸🅼kunheeya@gmail.com(Project No.10) C++, STL, 자료구조[42seoul] Webserv : 멀티플렉싱 웹서버 개발2021-03-09T00:00:00+09:002021-05-03T21:10:00+09:00https://kunhee.kim/42seoul/project-42seoul-webserv<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/22">Webserv : 멀티플렉싱 웹서버 개발</a></p>
<h1 id="-webserv">🤖 Webserv</h1>
<p><code class="language-plaintext highlighter-rouge">Youpi Webserv</code> by <a href="https://github.com/tomhato">yeha</a>, <a href="https://github.com/yeosong1">yeosong</a> and <a href="https://github.com/ku-kim">kukim</a><br />
@42seoul : (2021.02.10 ~ 2021.05.03)</p>
<h2 id="-about">📖 About</h2>
<ul>
<li><code class="language-plaintext highlighter-rouge">Nginx</code>와 유사한 웹서버 개발</li>
<li>멀티 프로세스, 쓰레드가 아닌 <code class="language-plaintext highlighter-rouge">멀티 플렉싱(Multiplexing)</code>을 활용하여 구현합니다.</li>
<li>작동은 Nginx와 유사하게 conf 파일로 웹서버를 셋업합니다.</li>
<li>Keyword : Socket Programming, HTTP/1.1 Request & Response, HTTP/1.1 Methods RFC, TCP/IP, Network, Multiplexing, Non-Blocking, Asynchronous, CGI, Webserver(Nginx)</li>
</ul>
<h2 id="-review">📝 Review</h2>
<ul>
<li>팀 프로젝트 진행을 위한 구글 코딩 컨벤션, github, Branch Workflow를 설정, 기능마다 코드리뷰, 페어코딩, 마지막에 refactoring 하기로 했다.</li>
<li>전반적으로 사전 지식이 없기 때문에 C를 활용한 소켓 프로그래밍을 중심으로 학습해가며 상황에 맞게 개선했다.
<ul>
<li>i.e. 싱글프로세스 웹서버의 한계 : 다수의 클라이언트 응답 처리 딜레이 문제
<ul>
<li>멀티프로세스, 멀티스레드, 멀티플렉싱 선택지 중 멀티플렉싱 선택</li>
</ul>
</li>
<li>i.e. 멀티 플렉싱 서버 구현 문제점 : 클라이언트의 요청에 따라 서버 자원을 read, write 하는데 fd에 Blocking이 걸려 지연 발생
<ul>
<li>fcntl()을 사용해 해당 fd를 Non-blocking 설정</li>
</ul>
</li>
<li>i.e. 클라이언트가 비정상 종료했을 때
<ul>
<li>서버 측에서 sigpipe의 시그널을 체크하고 비정상 종료 때 해당 socket fd 닫기</li>
</ul>
</li>
<li>i.e. 서버 비정상 종료, 재시작 Time-wait bind() 재할당 문제
<ul>
<li>SO_REUSEADDR 옵션으로 bind() 문제 제거</li>
</ul>
</li>
<li>i.e. RFC 문서에 따라 HTTP/1.1 헤더를 구현하는데 크고 작은 어려움들이 많았고 실제로 구현되어 있는 부분에 대한 이해가 깊어졌다.
<ul>
<li>e.g. <code class="language-plaintext highlighter-rouge">Accept-Language</code> 요청에 따라 content negotiation 하는 알고리즘이 RFC 문서에 특정하지 않기 때문에 직접 구현했다.</li>
<li>e.g. <code class="language-plaintext highlighter-rouge">Transfer-Encoding:chunked</code> 요청 헤더가 있다면 서버측에서 전송할 때 데이터를 나눠서 보내고 끝 메세지에 개행 두번 + EOF</li>
<li>e.g. nginx에서 리다이렉트와 리버스 프록시를 손쉽게 사용하는데 구현은 클라이언트 특정 리소스 요청이 redirect 되는 리소스라면 서버 측에서 단순하게 클라이언트에게 redirect 되었다고 <code class="language-plaintext highlighter-rouge">Location:uri</code> 응답 헤더를 보낸다. 이에 클라이언트가 해당 리소스에 재요청 한다. 리버스 프록시는 서버측에서 <code class="language-plaintext highlighter-rouge">Location:uri</code>를 클라이언트에게 보내지 않고 리다이렉트된 리소스를 찾아 클라이언트에게 응답해준다. 구현할 땐 아주 단순한 부분이지만 기능 차이가 크다.</li>
</ul>
</li>
</ul>
</li>
<li>개선 사항
<ul>
<li>현재 서버는 멀티 플렉식 (select() + fcntl()(non-blocking + asynchronous))으로 되어있지만 cgi를 제외하고 싱글 프로세스로 작동한다. nginx에서는 conf 파일에서 Worker Process 을 설정으로 프로세스 개수를 설정할 수 있는데, 현재 구현한 webserv에서도 cpu 작업이 오래걸리는 요청이 있다면 애초에 멀티 프로세스,스레드를 만들어 처리하면 처리 속도가 증가할 수 있겠다.</li>
<li>테스트 코드와 refactoring에 빈약하다.</li>
<li>웹서버의 log가 부족하다.</li>
</ul>
</li>
</ul>
<h2 id="-run">🏁 Run</h2>
<ul>
<li>
<p>HTTP Method test : GET, HEAD, POST
<img src="https://user-images.githubusercontent.com/57086195/122648307-a54a2780-d163-11eb-9866-eb5be27841a7.gif" alt="Methods2" /></p>
</li>
<li>
<p>Content negotiation, Redirect
<img src="https://user-images.githubusercontent.com/57086195/122648272-6c11b780-d163-11eb-875d-99bc4efd59c1.gif" alt="nego_redir" /></p>
</li>
<li>
<p>Authorization, Server pause 503, Siege test
<img src="https://user-images.githubusercontent.com/57086195/122648285-91062a80-d163-11eb-9e77-7976946e4cc2.gif" alt="auth_503_siege" /></p>
</li>
</ul>
<hr />
<h2 id="구현-사항">구현 사항</h2>
<ul>
<li>nginx
<ul>
<li>config file</li>
<li>Host, Port</li>
<li>Server name</li>
<li>setup default</li>
<li>limit client body size</li>
<li>Accepted HTTP Methods for the route</li>
<li>autoindex On/Off</li>
<li>redirect</li>
<li>execute CGI (RFC 3275 참고)</li>
</ul>
</li>
<li>HTTP 헤더(RFC 7230 ~ 7235, HTTP/1.1을 참고하여 아래 헤더를 구현합니다.)
<ul>
<li>Accept-Charsets</li>
<li>Accept-Language</li>
<li>Allow</li>
<li>Authorization</li>
<li>Content-Language</li>
<li>Content-Length</li>
<li>Content-Location</li>
<li>Content-Type</li>
<li>Date</li>
<li>Host</li>
<li>Last-Modified</li>
<li>Location</li>
<li>Referer</li>
<li>Retry-After</li>
<li>Server</li>
<li>Transfer-Encoding</li>
<li>User-Agent</li>
<li>WWW-Authenticate
<h2 id="-reference">🔗 Reference</h2>
</li>
</ul>
</li>
<li><a href="https://linux.die.net/man/1/bash">man : bash</a></li>
<li><a href="https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html">gnu Bash Reference Manual</a></li>
</ul>
<h2 id="-author">🧑🏻💻 Author</h2>
<p><a href="https://github.com/tomhato">yeha</a><br />
<a href="https://github.com/ku-kim">kukim</a></p>🅺🆄🅺🅸🅼kunheeya@gmail.com(Project No.11) C++, web server, nginx, HTTP/1.1, Socket, Multiplexing[42seoul] CPP Modules : C++ 익히기2021-02-07T00:00:00+09:002021-02-07T18:10:00+09:00https://kunhee.kim/42seoul/project-42seoul-cpp_modules<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/19">CPP Modules : C++을 활용한 OOP 익히기</a></p>
<h1 id="-cpp-moudle-08">📚 CPP Moudle 08</h1>
<p>@42seoul : (2021.01.21 ~ 2020.02.07)</p>
<h2 id="-about">📖 About</h2>
<ul>
<li>이 프로젝트는 CPP 언어에 대한 기초 문법와 OOP, STL 라이브러리를 학습합니다.</li>
<li>CPP의 기초 개념을 구현합니다.</li>
</ul>
<h2 id="-학습-내용">📝 학습 내용</h2>
<ul>
<li>CPP 0 : 클래스, 생성자, 입출력</li>
<li>CPP 1 : 동적할당, 소멸자, 레퍼런스, 함수 오버로딩</li>
<li>CPP 2 : 임시 다형성, 연산자 오버로딩, 캐노니컬 폼</li>
<li>CPP 3 : 상속, 다중상속</li>
<li>CPP 4 : 다형성, 추상클래스, 순수 가상함수, 인터페이스</li>
<li>CPP 5 : 예외처리</li>
<li>CPP 6 : 형변환(static, reinterpret, dynamic, const)</li>
<li>CPP 7 : 템플릿(function, function pointer, class)</li>
<li>CPP 8 : STL(Standard Templated Library: Containers, iterators, algorithms)</li>
</ul>
<hr />
<h2 id="-reference">🔗 Reference</h2>
<ul>
<li><a href="http://cplusplus.com/">cplusplus - The C++ Resources Network</a></li>
<li><a href="https://en.cppreference.com/w/">cppreference</a></li>
<li><a href="https://modoocode.com/135">씹어먹는 C++ 강좌 계획</a></li>
<li><a href="https://www.youtube.com/channel/UCHcG02L6TSS-StkSbqVy6Fg/playlists?view=50&sort=dd&shelf_id=2">코드없는 프로그래밍</a></li>
</ul>
<h2 id="-author">🧑🏻💻 Author</h2>
<p><a href="https://github.com/ku-kim">kukim</a></p>🅺🆄🅺🅸🅼kunheeya@gmail.com(Project No.9) C++, OOP[42seoul] Philosophers : 식사하는 철학자 문제2021-01-20T00:00:00+09:002021-01-20T23:10:00+09:00https://kunhee.kim/42seoul/project-42seoul-philosophers<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/18">Philosophers : 식사하는 철학자 문제</a></p>
<h2 id="-philosophers">📚 Philosophers</h2>
<p>@42seoul : (2021.01.04 ~ 2021.01.20)</p>
<h2 id="-about">📖 About</h2>
<ul>
<li>이 프로젝트는 기본적인 프로세스 스레딩, mutex, semaphore, shared memory을 배웁니다.(In this project, you will learn the basics of threading a process and how to work on the same memory space. You will learn how to make threads. You will discover the mutex, semaphore and shared memory.)</li>
<li>C언어를 활용하여 <a href="https://en.wikipedia.org/wiki/Dining_philosophers_problem">Dining philosophers problem</a> 문제를 3가지 방법으로 구현합니다.</li>
</ul>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/7/7b/An_illustration_of_the_dining_philosophers_problem.png" alt="philo" /></p>
<ul>
<li><a href="https://upload.wikimedia.org/wikipedia/commons/7/7bAn_illustration_of_the_dining_philosophers_problem.png">사진 출처 : wiki</a></li>
</ul>
<h4 id="프로그램-사항">프로그램 사항</h4>
<ol>
<li>Program 1 <code class="language-plaintext highlighter-rouge">philo_one</code> : Mutex
<ul>
<li>철학자는 쓰레드이다.</li>
<li>원탁에 앉아있고, 양 옆에 포크가 있다.</li>
</ul>
</li>
<li>Program 2 <code class="language-plaintext highlighter-rouge">philo_two</code> : Semaphore
<ul>
<li>철학자는 쓰레드이다.</li>
<li>원탁에 앉아있고, 테이블 중앙에 포크가 있다.</li>
</ul>
</li>
<li>Program 3 <code class="language-plaintext highlighter-rouge">philo_three</code> : shared memory
<ul>
<li>철학자는 프로세스이다.</li>
<li>원탁에 앉아있고, 테이블 중앙에 포크가 있다.</li>
</ul>
</li>
</ol>
<ul>
<li>조건
<ul>
<li>철학자는 2명 이상이다.</li>
<li>철학자는 정해진 시간 안에 먹지 않으면 죽는다.</li>
<li>철학자 한 명이 죽으면 프로그램을 종료한다. (죽는 시간 기준10ms 안에 종료 메세지를 보내야 한다.)</li>
<li>철학자는 먹기위해 포크 2개를 집어야 한다.</li>
<li>철학자는 먹고 -> 자고 -> 생각하는 것을 반복한다.</li>
<li>프로그램 실행 인자는 총 5개 or 6개이다.</li>
<li><code class="language-plaintext highlighter-rouge">./philo_one number_of_philosophers time_to_die time_to_eat time_to_sleep [number_of_times_each_philosopher_must_eat]</code></li>
<li>ex) <code class="language-plaintext highlighter-rouge">./philo_one 2 310 100 100 2</code> 으로 실행한다면
<ul>
<li>철학자 수 2명</li>
<li>310ms안에 먹어야 철학자 생존</li>
<li>100ms동안 먹는다</li>
<li>100ms동안 잔다</li>
<li>모든 철학자가 2번 먹으면 프로그램 종료</li>
</ul>
</li>
<li>철학자는 프로그램에 따라 쓰레드이기도 하고 프로세스이기도 하다.</li>
</ul>
</li>
</ul>
<h2 id="-review">📝 Review</h2>
<ul>
<li>쓰레드나 프로세스 사이에 실행 시기를 맞추는 동안(동기화(Synchronization))에 문제가 발생할 수 있다.</li>
<li>예를 들어 A, B, C 쓰레드가 공유하고 있는 <code class="language-plaintext highlighter-rouge">int count</code>라는 변수를 동시에 수정한다면 결과가 이상하게 나올 것 이다. 또한 두 개의 작업이 서로 상대방의 작업이 끝나길 무한히 기다리거나(deadlock, 교착상태) 우선순위가 낮아서 아예 자원할당을 받지 못하는 경우도 있다(stravation, 기아상태).</li>
<li>이를 해결하기 위해 공유하고 있는 data를 Exclusive Access, 어느 한 스레드가 공유 변수를 사용하는 동안 다른 스레드가 접근하지 못하도록 막는 방법을 공부했다.</li>
<li>Mutex와 Semaphore에 대한 이론적 개념과 이를 간단한 예제를 통해 구현할 수 있었다.</li>
</ul>
<h2 id="-run">🏁 Run</h2>
<ul>
<li>Test
<ul>
<li>./program 5 800 200 200 7 : 7번 다 먹으면 프로그램 종료</li>
<li>./program 4 410 200 200 : 무한 루프</li>
<li>./program 2 310 200 100 (10ms 안에 죽는 것 확인)</li>
</ul>
</li>
</ul>
<ol>
<li>philo_one : Mutex version</li>
</ol>
<p><img src="https://user-images.githubusercontent.com/57086195/105130787-01643d80-5b2b-11eb-8ce9-a1f6b5b0f80d.gif" alt="philo_one" /></p>
<ol>
<li>philo_two : Semaphore version</li>
</ol>
<p><img src="https://user-images.githubusercontent.com/57086195/105130785-00cba700-5b2b-11eb-9fd7-7aedf9ee24b3.gif" alt="philo_two" /></p>
<ol>
<li>philo_three : Shared memory version</li>
</ol>
<p><img src="https://user-images.githubusercontent.com/57086195/105130782-ff01e380-5b2a-11eb-96a2-595089402d80.gif" alt="philo_three" /></p>
<hr />
<h2 id="-reference">🔗 Reference</h2>
<ul>
<li><a href="https://github.com/ku-kim/Project_42seoul">🖼 전체 42seoul Project repo</a></li>
<li><a href="https://en.wikipedia.org/wiki/Dining_philosophers_problem">wiki : Dining philosophers problem</a></li>
<li><a href="https://www.geeksforgeeks.org/dining-philosopher-problem-using-semaphores/">Dining Philosopher Problem Using Semaphores</a></li>
<li><a href="https://youtu.be/YAP0Bv_aQl8">운영체제: 16. 철학자들은 왜 굶어 죽었을까? (철학자들의 저녁식사 문제)</a></li>
<li><a href="https://youtu.be/07d7I6GnCZ0">06.6 기아상태</a></li>
</ul>
<h2 id="-author">🧑🏻💻 Author</h2>
<p><a href="https://github.com/ku-kim">kukim</a></p>🅺🆄🅺🅸🅼kunheeya@gmail.com(Project No.8) C, Mutex, Semaphore, Shared memory, OS[42seoul] ft_services : Kubernetes를 활용한 (작은) 서비스 아키텍쳐 배포2021-01-13T00:00:00+09:002021-01-13T23:10:00+09:00https://kunhee.kim/42seoul/project-42seoul-ft_services<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/17">Kubernetes를 활용한 (작은) 서비스 아키텍쳐 배포</a></p>
<h2 id="-ft_services">🎶 ft_services</h2>
<p>@42seoul : (2020.12.15 ~ 2021.01.13)</p>
<h2 id="-about">📖 About</h2>
<ul>
<li>Kubernetes를 활용하여 아래의 아키텍쳐를 구현하시오.</li>
<li>Docker 빌드는 Dockerhub를 사용하지 않고 직접 DOCKERFILE을 만듭니다. (OS : alpine)</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/104842939-76f1c300-590b-11eb-9f81-0305626ccb74.png" alt="ft_service_draw" /></p>
<h2 id="-run">🏁 Run</h2>
<h4 id="1start-setupsh">1.Start setup.sh</h4>
<ul>
<li>minikube setting</li>
<li>docker build</li>
<li>kubectl apply</li>
<li>Dashboard</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/105048154-92e19a00-5aae-11eb-826c-f0d4657af6ef.gif" alt="setup" /></p>
<h4 id="2-kubernetes-시연">2. kubernetes 시연</h4>
<ul>
<li>Deploy : Nginx
<ul>
<li>redir : http://192.168.99.152 -> https://192.168.99.152</li>
<li>ssh www:kukim@192.168.99.152</li>
</ul>
</li>
<li>Deploy : FTPS
<ul>
<li>upload : curl ftp://kukim:kukim@192.168.99.152 -T setup.sh</li>
<li>download : curl ftp://kukim:kukim@192.168.99.152/setup.sh -o test.sh</li>
<li>k exec pod/ftp -it – /bin/sh</li>
</ul>
</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/105048180-9aa13e80-5aae-11eb-80f9-f7b8916397a9.gif" alt="nginx_ftps" /></p>
<ul>
<li>Deploy : phpmyadmin, wordpress, mysql
<ul>
<li>redir : http://192.168.99.152/wordpress -> 192.168.99.152:5050</li>
<li>revers proxy : http://192.168.99.152/phpmyadmin -> 192.168.99.152:5000</li>
</ul>
</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/105048184-9bd26b80-5aae-11eb-8f91-2263f2e93d1f.gif" alt="word_php_my" /></p>
<ul>
<li>Deploy : Grafana, influxDB, telegraf
<ul>
<li>192.168.99.152:3000</li>
<li>k delete deploy:influxdb -> pv 저장공간 check</li>
<li>k apply -f influxdb -> 재연결 okay</li>
</ul>
</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/105048189-9d039880-5aae-11eb-98d0-827bd5b44209.gif" alt="grafana_influxdb" /></p>
<h4 id="3-pkill-app-in-pods---restart">3. pkill App in Pods -> restart</h4>
<ul>
<li>kubectl exec deploy/nginx – pkill nginx</li>
<li>kubectl exec deploy/ftps – pkill vsftpd</li>
<li>kubectl exec deploy/grafana – pkill grafana</li>
<li>kubectl exec deploy/telegraf – pkill telegraf</li>
<li>kubectl exec deploy/influxdb – pkill influx</li>
<li>kubectl exec deploy/wordpress – pkill php-fpm7</li>
<li>kubectl exec deploy/mysql – pkill /usr/bin/mysqld</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/105048176-9a08a800-5aae-11eb-8233-04a276301661.gif" alt="pkill" /></p>
<h2 id="-review">📖 Review</h2>
<ul>
<li>kubernetes, 컨테이너 오케스트레이션는 아름답다. 네트워크를 통해서 수 많은 클러스터를 하나의 서버처럼 사용하고, 각각의 쿠버네티스 Object들을 .yaml로 상태 관리하고 유연하게 서비스 확장이 가능하며 배포, 롤백 및 버전 관리에 탁월하며 다양한 볼륨 연결할 수 있다니 대단하다. 구글 크기의 회사가 쿠버네티스로 운영해도 문제가 없다고 하니 구글보다 큰 기업이지 않는 이상 쿠버네티스로 모든 해결되지 않을까 생각이 들었다. 하지만 작은 서비스에겐 오버 스펙이라고 느껴졌다.</li>
<li>kubernetes의 개념, 기본적인 Object(pod, deployment, service …), 외부 접속 설정(Cluster IP, LoadBalancer), 스케일 아웃을 맛보았다. (아! 쿠버네티스가 이런거구나?!)</li>
<li>아쉬운 점 : 실무에서 진행한 프로젝트가 실무에선 어느정도 수준일까 궁금했고, 실제로 어떻게 구현할까 의문이 들었다. 또한 추후에 CI/CD 적용과 kubeflow 서비스도 추가해볼 생각이다.</li>
</ul>
<hr />
<h2 id="-reference">🔗 Reference</h2>
<ul>
<li><a href="https://github.com/ku-kim/Project_42seoul">🖼 전체 42seoul Project repo</a></li>
<li><a href="https://kubernetes.io//docs/tutorials/">kubernetes 공식 Doc Tutorial</a></li>
<li><a href="https://subicura.com/k8s/?fbclid=IwAR2l6yjJC1HhTVltRacVKicVf6arR-XEhDCTgHlqmRXhLRS4Y9PH6CETrjg">쿠버네티스 안내서</a></li>
<li><a href="https://youtu.be/SNA1sSNlmy0">44BITS-초보를 위한 쿠버네티스 안내서</a></li>
<li><a href="https://www.inflearn.com/course/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EA%B8%B0%EC%B4%88/dashboard">대세는 쿠버네티스 초급~중급</a></li>
</ul>
<h2 id="-author">🧑🏻💻 Author</h2>
<p><a href="https://github.com/ku-kim">kukim</a></p>🅺🆄🅺🅸🅼kunheeya@gmail.com(Project No.7) DevOps, Kubernetes, Container orchestration[42seoul] minishell : 나만의 bash, 쉘 프로그램 만들기!2021-01-03T00:00:00+09:002021-01-03T23:10:00+09:00https://kunhee.kim/42seoul/project-42seoul-minishell<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/16">minishell : 나만의 bash, 쉘 프로그램 만들기!</a></p>
<h2 id="️-minishell">⌨️ minishell</h2>
<p><code class="language-plaintext highlighter-rouge">heeheeshell</code> by <a href="https://github.com/tomhato">yeha</a> and <a href="https://github.com/ku-kim">kukim</a><br />
@42seoul : (2020.11.10 ~ 2021.01.03)</p>
<h2 id="-about">📖 About</h2>
<ul>
<li>간단한 <strong>쉘</strong> 프로그램을 구현합니다.(The objective of this project is for you to create a simple shell.)</li>
<li>작동은 bash와 동일합니다.</li>
<li>bash의 작동 방식, Standard Stream, foreground & background process, fork, IPC, pipe, execve, signal 등을 공부합니다.</li>
<li>이전 프로젝트 libft, get_next_line 활용</li>
<li>구현 목록
<ul>
<li>echo, exit, return value, env, export, unset, cd, pwd</li>
<li>$PATH</li>
<li>multiline string</li>
<li>그 외 command : /bin/[command]</li>
<li>redir(<, >, »)</li>
<li>
<table>
<tbody>
<tr>
<td>pipe(</td>
<td>)</td>
</tr>
</tbody>
</table>
</li>
</ul>
</li>
</ul>
<h2 id="-review">📝 Review</h2>
<ul>
<li>사전 지식을 얻기 위해 <a href="https://github.com/Kraken-Addicts/Operating-System">OS 스터디</a>를 두 달 동안 진행하며 연습 문제도 함께 제출했다.</li>
<li>가장 많이 사용하는 <strong>쉘</strong>의 내부 동작을 알게 되었다. 개인적으로 매우 놀라운 일이다.ex)zsh에서 ls -al 명령어 실행하면 zsh는 자식 프로세스를 만들고 그 자식 프로세스는 /bin/ls 를 실행한다니! 놀랍지 아니한가?</li>
<li>부모/자식 프로세스 생성, IPC통신에 대해 이해하게 되었고 signal과 exit 종료 코드도 알게되었다.</li>
<li>Nginx 서비스를 백그라운드로 실행할 때 어떻게 동작할까? 궁금했는데 이 프로젝트를 통해 부모/자식 프로세스 분기 후 부모 프로세스가 waitpid() 하지 않고 종료하면 된다는 것도 알게 되었다.</li>
<li>한 줄 평 : 아니 내가 쉘을 만들었다고? 👏👏👏👏</li>
</ul>
<h2 id="-run">🏁 Run</h2>
<ul>
<li>
<p>echo, Multi line, exit, return value, ‘;’ cat, cd, pwd
<img src="https://user-images.githubusercontent.com/57086195/104806644-60b90980-581c-11eb-8fbe-2c2e6c93fb28.gif" alt="heeheeshell_1" /></p>
</li>
<li>
<p>env, export, unset, Signal(Ctrl + C, \, D), redir, pipe
<img src="https://user-images.githubusercontent.com/57086195/104806649-66aeea80-581c-11eb-984e-d0daff6a9c85.gif" alt="heeheeshell_2" /></p>
</li>
</ul>
<hr />
<h2 id="-reference">🔗 Reference</h2>
<ul>
<li><a href="https://github.com/ku-kim/Project_42seoul">🖼 전체 42seoul Project repo</a></li>
<li><a href="https://linux.die.net/man/1/bash">man : bash</a></li>
<li><a href="https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html">gnu Bash Reference Manual</a></li>
</ul>
<h2 id="-author">🧑🏻💻 Author</h2>
<p><a href="https://github.com/tomhato">yeha</a><br />
<a href="https://github.com/ku-kim">kukim</a></p>🅺🆄🅺🅸🅼kunheeya@gmail.com(Project No.6) C, Shell, Bash, OS, Computer-Achitecture[42seoul] libasm : assembly(어셈블리)를 활용한 나만의 라이브러리 구현2020-12-01T00:00:00+09:002020-12-01T23:10:00+09:00https://kunhee.kim/42seoul/project-42seoul-libasm<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/15">libasm : assembly(어셈블리)를 활용한 몇 개의 함수 구현</a></p>
<h2 id="0️⃣1️⃣-libasm">0️⃣1️⃣ libasm</h2>
<p>@42seoul : (2020.11.20 ~ 2020.12.01)</p>
<h2 id="-about">📖 About</h2>
<ul>
<li>이 프로젝트는 어셈블리 언어를 가지고 몇 가지 함수를 구현합니다.(The aim of this project is to get familiar with assembly language.)</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align: center">Type</th>
<th style="text-align: center">Function</th>
<th style="text-align: left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><string.h></string.h></td>
<td style="text-align: center">ft_strlen.s</td>
<td style="text-align: left">man strlen</td>
</tr>
<tr>
<td style="text-align: center"><string.h></string.h></td>
<td style="text-align: center">ft_strdup.s</td>
<td style="text-align: left">man strdup</td>
</tr>
<tr>
<td style="text-align: center"><string.h></string.h></td>
<td style="text-align: center">ft_strcpy.s</td>
<td style="text-align: left">man strcpy</td>
</tr>
<tr>
<td style="text-align: center"><string.h></string.h></td>
<td style="text-align: center">ft_strcmp.s</td>
<td style="text-align: left">man strcmp</td>
</tr>
<tr>
<td style="text-align: center"><fcntl.h></fcntl.h></td>
<td style="text-align: center">ft_write.s</td>
<td style="text-align: left">man write</td>
</tr>
<tr>
<td style="text-align: center"><fcntl.h></fcntl.h></td>
<td style="text-align: center">ft_open.s</td>
<td style="text-align: left">man open</td>
</tr>
</tbody>
</table>
<ul>
<li>write, read 함수는 systemcall 호출하고 error 발생 시 __error 호출하여 errno를 저장하고 끝내야 합니다.</li>
</ul>
<h2 id="-review">📝 Review</h2>
<ul>
<li>assembly language를 경험할 수 있었다.</li>
<li><a href="https://github.com/Kraken-Addicts/Computer-Achitecture">Computer-Achitecture 스터디</a>도 함께 진행했다.</li>
<li>CPU, 레지스터, Stack 메모리를 이해하게 되었고 read, write함수를 구현하면서 각각의 시스템콜 번호를 호출하면 커널모드로 변경 되며 sys_open() 커널 함수가 호출되고 함수가 끝나면 다시 사용자 모드로 바뀌고 결과가 리턴된다. 이때 시스템콜이 에러가 발생하면 캐리플래그가 발생되고 rax 레지스터에 errno가 들어있다. 이것을 __error를 호출하여 error를 나타내는 변수에 rax 결과를 저장한 뒤 최종적으로 -1을 리턴하고 종료된다.</li>
<li>Level 0 프로젝트 <a href="https://github.com/ku-kim/Project_42seoul/tree/master/libft">Libft</a>에서 만들었던 ft_strlen과 Libc의 strlen 벤치마크 결과 완패했는데 그 이유가 어셈블리 단에서 최적화 과정을 거쳤기 때문이지 않을까 한다.</li>
</ul>
<h2 id="-run">🏁 Run</h2>
<ul>
<li>Assembly Env
<ul>
<li>nasm compiler</li>
<li>x86_64 macos</li>
<li>intel</li>
</ul>
</li>
<li>Unit-test : Libc - 어셈블리 구현 함수 비교
<img src="https://user-images.githubusercontent.com/57086195/104812738-9de6c100-5847-11eb-8be1-e458c7862e9d.gif" alt="libasm" /></li>
</ul>
<p>├── Makefile<br />
├── ft_read.s<br />
├── ft_strcmp.s<br />
├── ft_strcpy.s<br />
├── ft_strdup.s<br />
├── ft_strlen.s<br />
├── ft_write.s<br />
├── libasm.h<br />
└── main.c</p>
<hr />
<h2 id="-reference">🔗 Reference</h2>
<ul>
<li><a href="https://github.com/ku-kim/Project_42seoul">🖼 전체 42seoul Project repo</a></li>
<li><a href="https://www.nasm.us/">nasm</a></li>
</ul>
<h2 id="-author">🧑🏻💻 Author</h2>
<p><a href="https://github.com/ku-kim">kukim</a></p>🅺🆄🅺🅸🅼kunheeya@gmail.com(Project No.5) Assembly, string.h, fcntl.h, nasm, OS, Computer-AchitectureJAVA의 컴파일과 실행2020-11-29T00:00:00+09:002020-12-06T02:10:55+09:00https://kunhee.kim/programming/basic-java-0<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/24">JAVA의 컴파일과 실행</a></p>
<h1 id="1-크로스플랫폼과-간단한-컴파일-과정">1. 크로스플랫폼과 간단한 컴파일 과정</h1>
<h2 id="11-크로스플랫폼">1.1 크로스플랫폼</h2>
<p>Java란 1991년 James Gosling, Mike Sheridan, and Patrick Naughton이 당시 프로그램을 작성하는데 특정 운영체제, 디바이스마다 다른 규격에 어려움을 느끼고 “Write once, run any where(WORA), 한 번 작성하면 어디서든 실행” 된다는 가치관을 가지고 (크로스플랫폼) 시작되었다.</p>
<blockquote>
<p>크로스 플랫폼 : 특정 언어의 같은 소스코드를 여러 운영체제, 플랫폼에서 실행 가능</p>
</blockquote>
<h2 id="12-c언어-컴파일-과정과-크로스플랫폼">1.2 C언어 컴파일 과정과 크로스플랫폼</h2>
<ol>
<li>소스코드 작성(.h, .c)</li>
<li>전처리 & 컴파일
<ul>
<li>input : 소스코드 (.h, .c) ⇒ <strong>전처리기</strong> ⇒ output : 트랜스레이션 유닛 (.pre)</li>
<li>input : 트랜스레이션 유닛(.pre) ⇒ <strong>컴파일러</strong> ⇒ output : 어셈블리어 코드 (.s)</li>
<li>input : 어셈블리어 코드(.s) ⇒ <strong>어셈블러</strong> ⇒ output : 오브젝트 코드 (.o)</li>
<li>
<table>
<tbody>
<tr>
<td>input : 오브젝트 코드(.o) ⇒ <strong>링커</strong> ⇒ output : 실행파일 (.out</td>
<td>.exe)</td>
</tr>
</tbody>
</table>
</li>
</ul>
</li>
<li>
<table>
<tbody>
<tr>
<td>실행파일 실행 (.out</td>
<td>.exe)</td>
</tr>
</tbody>
</table>
</li>
</ol>
<p>C언어의 컴파일 최종 결과는 실행파일이 나온다. 이 실행파일은 특정 운영체제(Linux, Window, MacOS) 전용 실행파일이기 때문에 Linux에서 만들 실행 파일(.out)을 Window에서 실행할 수 없다. 하지만 Linux에서 작성한 C언어 소스 코드를 Window 전용 컴파일러로 컴파일 한다면 Window에서 실행할 수 있다. 이처럼 C언어는 소스코드에 대해선 크로스 플랫폼이라 할 수 있고 컴파일 결과에 대해선 그렇지 않다 라고 할 수 있다.</p>
<h2 id="13-크로스플랫폼-java-컴파일-과정">1.3 크로스플랫폼, Java 컴파일 과정</h2>
<ol>
<li>소스코드 작성 (.java)</li>
<li>컴파일 - input : 소스코드(.java) ⇒ <strong>컴파일(javac)</strong> ⇒ output : .class(bytecode)</li>
<li>JVM에서 바이트코드 실행</li>
</ol>
<p>자바의 컴파일 최종 결과는 실행파일이 아닌 바이트코드(bytecode)이다. 이는 특정 운영체제가 이해할 수 있는 기계어가 아니며 JVM(Java Virtual Machine)이라는 프로그램이 이해할 수 있는 명령어이다. C언어 같은 경우에는 운영체제가 실행할 수 있는 결과로 컴파일 되어 각 운영체제에 종속되어 바로 실행 할 수 있는 반면 Java는 바이트코드로 컴파일 되면 운영체제와 상관없이 실행할 운영체제에서 JVM이란 프로그램을 설치하면 그 위에서 실행할 수 있다. 이는 C와는 다르게 소스코드와 컴파일된 후의 바이트코드에서 크로스 플랫폼이라 할 수 있는데 문제는 JVM이 설치되어 있지 않다면 실행할 수 없다는 문제가 있다. 이를 두고 완벽한 크로스 플랫폼이라 할 수 있는가 의문이 남는다.</p>
<ul>
<li>컴파일러를 프로그래밍 언어 → 기계어로 바꾸는 과정이라 말한다면 javac는 100 컴파일러라고 할 순 없지만 사람이 이해할 수 없는 코드로 변환하는 과정이 있으므로 컴파일러라 하자. 실제 기계어로 바꾸는 과정은 뒤쪽의 JIT 컴파일 과정이 있다.</li>
</ul>
<blockquote>
<p>Bytecode : JVM의 인터프리터가 효율적으로 실행할 수 있는 형태(기계어가 아니다.)</p>
</blockquote>
<p><img src="https://user-images.githubusercontent.com/57086195/101237378-829e7700-371b-11eb-8aba-8aeee80afe52.png" alt="java_compile" /></p>
<h1 id="2-hello-world-컴파일--실행">2. Hello World! (컴파일 & 실행)</h1>
<ul>
<li>아래 코드는 Hello, World! 를 커맨드 창에 출력하는 코드이다.
<ul>
<li>소스코드 내용은 다음에 이야기하기로 하고 이곳에선 컴파일(빌드)와 실행을 살펴본다.</li>
</ul>
</li>
</ul>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Main.java</span>
<span class="kn">package</span> <span class="nn">com.kukim</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="21-컴파일">2.1 컴파일</h2>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># javac -d <컴파일 결과 저장할 경로> <컴파일할 .java 파일></span>
<span class="c"># -d : .class 파일 저장할 경로</span>
<span class="c"># class란 폴더가 없을 땐 자동으로 생성된다.</span>
javac <span class="nt">-d</span> class/ srcs/com/kukim/<span class="k">*</span>.java
</code></pre></div></div>
<script id="asciicast-375995" src="https://asciinema.org/a/375995.js" async=""></script>
<ul>
<li>javap 를 활용한 bytecode opcode check!</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>javap <span class="nt">-c</span> Main.class
</code></pre></div></div>
<ul>
<li>bytecode 내용을 살펴보면 각 코드 번호와 명령어 aload_0, invokevirtual, return 등이 있는데 이것이 JAVA에서 사용하는 opcode 이다. 이 opcode가 1바이트로 되어 있어서 bytecode라 불리며 8비트이기 때문에 2^8 = 256개의 바이트코드를 가지고 있고 모두 사용되고 있진 않다.
<script id="asciicast-oXABiildf09cHBT6s1Fh42kg7" src="https://asciinema.org/a/oXABiildf09cHBT6s1Fh42kg7.js" async=""></script></li>
</ul>
<h2 id="22-run">2.2 RUN</h2>
<p>컴파일한 .class(bytecode) 파일을 JVM에서 실행된다.</p>
<h3 id="221-java--classpath를-활용한-실행">2.2.1. java -classpath를 활용한 실행</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># java -classpath <class 파일 위치> <클래스이름></span>
java <span class="nt">-classpath</span> class/ com.kukim.Main
</code></pre></div></div>
<script id="asciicast-375996" src="https://asciinema.org/a/375996.js" async=""></script>
<h3 id="222-jar-파일을-활용한-실행">2.2.2 jar 파일을 활용한 실행</h3>
<ul>
<li>소스코드가 적을 때는 위의 실행처럼 단일 .class 파일만 실행하면 된다. 하지만 많은 양의 소스코드를 넘겨줄 땐 C나 C#의 .dll 이나 lib으로 만들어 배포하듯이 JAVA에서는 .jar 압축 파일형태로 묶어 배포한다. jar은 단순히 .zip 파일과 유사하지만 그 안에 META-INF라는 폴더에 MANIFEST 파일에 압축 하일에 대한 상세 내용이 들어 있고 JVM은 이 데이터를 가지고 실행한다.</li>
<li>따라서 jar로 압축할 때 Manifest.txt 파일을 활용해 내 소스코드의 main 함수 위치(entry point)를 알려주어야 한다.</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 1. Manifest.txt 파일 만들기</span>
<span class="c"># 2. jar로 압축하기</span>
jar <span class="nt">-cfm</span> <jar 저장할 디렉토리> <Manifest.txt 위치> <최상단 .class 디렉토리 위치>
<span class="c">## -c : create / -f : .jar 파일 이름 설정 / -m : manifest 파일 경로</span>
<span class="c"># 3. java로 실행하기</span>
java <span class="nt">-jar</span> ./lib/deploy.jar
</code></pre></div></div>
<script id="asciicast-s6jZTPGR1tuQn5hyjUaHhYlSD" src="https://asciinema.org/a/s6jZTPGR1tuQn5hyjUaHhYlSD.js" async=""></script>
<h3 id="223-ide를-활용한-실행">2.2.3 IDE를 활용한 실행</h3>
<ul>
<li>항상 자바를 실행할 때 위의 복잡한 과정을 거쳐야 하는가? NO!</li>
<li>실제로는 IDE를 활용해 컴파일, 실행한다.</li>
<li>Intellij & Eclipse을 활용하자.</li>
</ul>
<h3 id="a-서로-다른-java-버전-간의-컴파일과-실행">+a) 서로 다른 JAVA 버전 간의 컴파일과 실행</h3>
<p>자바는 버전 1부터 현재 15까지 있다.</p>
<ul>
<li>java 14의 javac(컴파일 옵션 X) 컴파일하여 java 8 버전에서 실행이 가능할까?
<ul>
<li>정답 : X</li>
</ul>
</li>
<li>java 8의 javac(컴파일 옵션 X) 컴파일하여 java 14 버전에서 실행이 가능할까?
<ul>
<li>정답 : O</li>
</ul>
</li>
<li>java 14의 javac(컴파일 옵션 O) 컴파일하여 java 8 버전에서 실행이 가능할까?
<ul>
<li>정답 : O</li>
</ul>
</li>
</ul>
<p>하위버전에서 컴파일한 자바 소스코드는 상위버전에서 문제없이 돌아가지만 상위버전애서 컴파일한 소스코드는 어떤 버전에서 실행할 지 컴파일 할 때 옵션을 주어야 하위 버전에서 실행할 수 있다.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># javac version = JAVA 14</span>
<span class="c">## 컴파일 옵션 : -source, -tartget 을 주어 1.8(java 8 명시)</span>
javac main.java <span class="nt">-source</span> 1.8 <span class="nt">-target</span> 1.8
<span class="c"># java 14에서 버전8 옵션을 주고 컴파일한 결과는 java 8 버전에서 문제없이 실행 가능</span>
java main.class
</code></pre></div></div>
<h1 id="jvm-구성-요소">JVM 구성 요소</h1>
<p>🔎 JVM(Java Virtual Machine) : javac를 통해 컴파일 된 .class(Bytecode)를 각각의 운영체제에 맞게 기계어로 번역하여 실행할 수 있게 만들어주는 프로그램이다.</p>
<h2 id="1-class-loader-sub-system">1. Class Loader Sub System</h2>
<ul>
<li>앞에서 컴파일된 .class file(bytecode)들을 로딩, 링킹, 초기화 단계를 거쳐 실제 메모리를 할당하는 역할을 한다.</li>
</ul>
<h2 id="2-runtime-data-area">2. Runtime Data Area</h2>
<ul>
<li>Class Loader sub System을 통해 할당된 메모리 공간이다.
<ol>
<li>Method Area</li>
<li>Heap Area</li>
<li>Stack Area</li>
<li>PC register</li>
<li>Native Method Stack</li>
</ol>
</li>
</ul>
<h2 id="3-execution-engine">3. Execution Engine</h2>
<h3 id="31-interpreter">3.1 Interpreter</h3>
<ul>
<li>컴파일된 .class의 바이트 코드를 기계어(0101010…)으로 변환하며 실행한다.</li>
<li>최초의 JVM은 인터프리터 방식이었다. 하지만 동일한 메서드를 매번 해석하여 실행하는 성능의 이슈가 발생하였다.</li>
</ul>
<h3 id="32-jitjust-in-time-compiler">3.2 JIT(Just In Time) Compiler</h3>
<ul>
<li>인터프리터의 성능 이슈를 해결하기 위해 생긴 방법이다.</li>
<li>자주 사용되는 메서드를 체크한 뒤 기계어로 변환한 뒤 캐싱하여 재사용하는 방법이다.</li>
<li>JIT 컴파일러는 모든 메소드에 사용되는 것이 아니다. 빈도가 적은 메소드에는 인터프리터가 더 빠를 수 있다.</li>
</ul>
<h3 id="33-gcgarbage-collector">3.3 GC(Garbage Collector)</h3>
<ul>
<li>C언어 같은 경우 동적 메모리 할당을 통해 힙 영역의 데이터를 읽고 쓴다. 이때 사용자가 직접 동적 메모리 할당을 해제해야 하는 어려움이 있다. (C = unmanaged language)</li>
<li>JAVA는 힙 영역의 메모리 관리를 사용자가 하지 않고 GC가 해준다. (JAVA = managed language)</li>
<li>이는 매우 강력하다.</li>
</ul>
<h2 id="4-native-method">4. Native Method</h2>
<ul>
<li>JAVA에서 C, C++, assembly로 작성된 라이브러리를 사용할 수 있게 도와준다.</li>
</ul>
<h1 id="jdk와-jre의-차이">JDK와 JRE의 차이</h1>
<ul>
<li>JDK(Java Development Kit)
<ul>
<li>JDK = JRE(JVM + Library) + JAVA 개발도구(컴파일러javac, 디버거 등)</li>
</ul>
</li>
<li>JRE(Java Runtime Environment)
<ul>
<li>JRE = JVM + Library</li>
<li>JAVA9 버전부터 더이상 JRE는 배포하지 않고 JDK만 배포한다.</li>
</ul>
</li>
</ul>
<hr />
<h1 id="reference-">Reference 🌏</h1>
<ul>
<li>
<p><a href="https://github.com/whiteship/live-study/issues/1">백기선 : JAVA Live study</a></p>
</li>
<li>
<p><a href="https://en.wikipedia.org/wiki/Java_(programming_language)#cite_note-17">wiki : Java (programming language)</a></p>
</li>
<li>
<p><a href="https://www.amazon.com/Java-Nutshell-Desktop-Quick-Reference/dp/1492037257">JAVA-Nutshell</a></p>
</li>
<li>
<p><a href="https://pocu-ko.teachable.com/p/comp2500">COMP2500: 개체지향 프로그래밍 및 설계 (Java)</a></p>
</li>
<li>
<p><a href="http://www.yes24.com/Product/Goods/24259565">자바의 정석</a></p>
</li>
</ul>🅺🆄🅺🅸🅼kunheeya@gmail.com크로스 플랫폼, 컴파일, 실행, JVM, JDK, JRE를 살펴봅니다.[42seoul] cub3d : Ray casting을 활용한 Wolfensteid3D 게임 개발2020-11-02T00:00:00+09:002020-11-02T23:10:00+09:00https://kunhee.kim/42seoul/project-42seoul-cub3d<p>블로그 이동 티스토리 -> <a href="https://kukim.tistory.com/14">cub3d : Ray casting을 활용한 Wolfensteid3D 유사 그래픽 구현</a></p>
<h2 id="-cub3d">📚 cub3d</h2>
<p>@42seoul : (2020.09.15 ~ 2020.11.02)</p>
<h2 id="-about">📖 About</h2>
<ul>
<li>이 프로젝트는 90년대 최초의 1인칭 슈팅 게임(<code class="language-plaintext highlighter-rouge">Wolfenstein 3D</code>)을 직접 구현합니다.(This project is inspired by the world-famous eponymous 90’s game(<code class="language-plaintext highlighter-rouge">Wolfenstein 3D</code>), which was the first FPS ever)</li>
<li>
<p><code class="language-plaintext highlighter-rouge">ray casting</code> 알고리즘을 공부합니다.</p>
</li>
<li>구현
<ul>
<li>mapfile에 따라 그래픽이 다르게 출력</li>
<li>벽, 장애물 통과 불가</li>
<li>–save 통해 플레이어 시작점 screenshot 저장</li>
<li>W,A,S,D,Q,E를 통해 이동, 시점 변환 가능, ESC 키 입력시 게임 종료</li>
<li>BGM, HUB 추가</li>
</ul>
</li>
</ul>
<h2 id="-review">📝 Review</h2>
<ul>
<li>C로 컴퓨터 그래픽 알고리즘을 구현해 게임을 만든다는 상상도 못했다.</li>
<li>2D 화면을 3D 처럼 보이게 만드는 <code class="language-plaintext highlighter-rouge">ray casting</code> 기술은 놀라웠다.(수학이 어려웠지만… 잘 구현했다.)</li>
<li>디테일하지 못한 부분도 많고, 완벽한 <code class="language-plaintext highlighter-rouge">Wolfenstein 3D</code>와 같진 않지만 추가 사항으로 HUB(Head up display)와 BGM 등 추가적인 요소를 넣으면서 게임 개발의 약간의 흥미를 갖게 되었다.</li>
<li>BGM을 사용을 위해 부모/자식 프로세스 fork() 활용</li>
<li>추가 개선사항 : multi thread, 마우스 사용, 게임적인 요소, 자연스러운 움직임</li>
</ul>
<h2 id="-run">🏁 Run</h2>
<ul>
<li>Basic Version</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/104799397-25194200-5812-11eb-9c68-26f848ef381f.gif" alt="cub3d_basic" /></p>
<ul>
<li>screenshot</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/104799400-29455f80-5812-11eb-8b69-e327000a386d.gif" alt="cub3d_screenshot" /></p>
<ul>
<li>인터스텔라 Version</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/57086195/104799399-277b9c00-5812-11eb-8e29-1a71948232d8.gif" alt="cub3d_bonus" /></p>
<hr />
<h2 id="-reference">🔗 Reference</h2>
<ul>
<li><a href="https://github.com/ku-kim/Project_42seoul">🖼 전체 42seoul Project repo</a></li>
<li><a href="http://users.atw.hu/wolf3d/">Original Game Wolfenstein 3D</a>
<img src="https://user-images.githubusercontent.com/57086195/104798832-3ad83880-580d-11eb-8ddc-eca9e64e0297.png" alt="wolf3d" /></li>
</ul>
<h2 id="-author">🧑🏻💻 Author</h2>
<p><a href="https://github.com/ku-kim">kukim</a></p>🅺🆄🅺🅸🅼kunheeya@gmail.com(Project No.4) C, ray casting, FPS, wolfensteid3D