<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>full_accel.log</title>
        <link>https://velog.io/</link>
        <description>스스로 배운 것이 오래 간다.</description>
        <lastBuildDate>Sun, 24 Jan 2021 14:58:34 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>full_accel.log</title>
            <url>https://images.velog.io/images/full_accel/profile/984eb020-7e1f-4369-8493-0e070cfee2f7/1442139146486.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. full_accel.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/full_accel" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[북스캔]]></title>
            <link>https://velog.io/@full_accel/%EB%B6%81%EC%8A%A4%EC%BA%94</link>
            <guid>https://velog.io/@full_accel/%EB%B6%81%EC%8A%A4%EC%BA%94</guid>
            <pubDate>Sun, 24 Jan 2021 14:58:34 GMT</pubDate>
            <description><![CDATA[<h1 id="북스캔이란">북스캔이란?</h1>
<p>스캐너로 책을 스캔해버리는 것. 이렇게 하면 더는 무거운 책을 들고 다니지 않아도 된다. 더불어 책을 모니터로 볼 수 있기 때문에 (특히 개발서 읽을 때) 여러모로 편하다.</p>
<p>보통 스캔한 결과물은 pdf 포맷으로 뽑히는데, 이 말은 pdf를 읽어들일 수 있는 디바이스면 그게 pc든 스마트폰이든, 태블릿이든 어디서든 내가 스캔한 책을 읽을 수 있다는 것이다. 편하다!</p>
<h1 id="불법-아님">불법 아님?</h1>
<p>법이 애매해서 특정 조건을 충족하면 합법인 걸로 알고 있다.(정확하진 않다.)</p>
<ul>
<li>일단 책을 돈 주고 사야 한다.</li>
<li>내가 내 책을 직접 스캔해야 한다.</li>
<li>당연히 내가 스캔했어도 유포하면 불법이다.</li>
</ul>
<p>법이 애매하기 때문에 북 스캐너를 잠시 사용할 수 있도록 해주는 업체도 있는 것으로 알고 있다. (북 스캔을 대행해주면 불법이지만, 북 스캔을 할 수 있도록 북 스캐너를 빌려주는 것은 불법이 아니다.)</p>
<h1 id="필요한-장비">필요한 장비</h1>
<h2 id="작두">작두</h2>
<p>일단 책의 기둥을 잘라서 책을 문서로 만들어야 한다. 요 작두도 종류가 많은데 아주 좋은 공업용을 사용하지 않는한 무슨 짓을 해도 책의 기둥을 아주 깔끔하게 잘하내는 것이 쉽지 않다. 가정에서 한다면 앵간하면 자르면서 어느정도 기울어진다고 봐야 한다.</p>
<h2 id="스캐너">스캐너</h2>
<p>내가 사용하는 모델은 ScanSnap ix500 이다. 요즘에는 50만원 정도 하는 것 같다. 3~4년 전에 구매할 때 60만원 중반에 구매했던 것으로 기억한다. 성능은 뭐 무난무난하다. 같이 딸려오는 소프트웨어가 일본 제품 답게 구질구질하다. OCR이 내장되어 있는데 개발서 OCR 돌리면 오류가 자주난다.(제대로 인식을 못하는 수준을 넘어서 그냥 오류 났어요 하고 OCR 실패한다.)</p>
<p>딱히 다른 대안이 없어서 사용중이다.</p>
<h2 id="보정-소프트웨어">보정 소프트웨어</h2>
<p><a href="https://scantailor.org/">scantailor</a>라는 소프트웨어가 있다. 위에서 말했듯 가정에서 사용할만한 작두로는 책을 아무리 이쁘게 자르려고 해도 책이 어느정도는 기울어져서 잘리기 때문에 스캔하면서 살짝 기울 수 있다.</p>
<p>이런 부분을 scantailor와 같은 소프트웨어로 후보정할 수 있다. 그런데 난 귀찮아서 잘 안한다.</p>
<h2 id="e-book-reader">e-book reader</h2>
<h3 id="pc">pc</h3>
<p>나는 PC에서 스캔한 책을 읽을 때 그냥 MS edge로 보는 편이다. 주로 세로로 세워놓은 모니터에서 개발서를 읽는 편이라 MS edge로 읽어도 크게 불편한점은 느끼지 못하고 있다.</p>
<h3 id="스마트폰-태블릿">스마트폰, 태블릿</h3>
<p>ReadEra 라는 앱을 사용한다.
기능 중에 여백 없애주는 기능이 있는데 화면이 작은 모바일 디바이스 특성상 요 기능이 참 유용하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HappyHacking Professional HYBRID Type-S 사용 후기]]></title>
            <link>https://velog.io/@full_accel/HappyHacking-Professional-HYBRID-Type-S-%EC%82%AC%EC%9A%A9-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@full_accel/HappyHacking-Professional-HYBRID-Type-S-%EC%82%AC%EC%9A%A9-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sun, 24 Jan 2021 14:43:32 GMT</pubDate>
            <description><![CDATA[<p>언제인지 정확히 기억은 나지 않지만 해피해킹이라는 키보드의 존재를 알게되었다. 찾아보면 키감이 아주 좋은데 배열이 극단적으로 UNIX 계열 OS에 최적화된 키보드라는 것이 중론이였다.</p>
<p>아무리 생각해도 VIM을 쓰는 것이 장기적으로는 유리하다고 판단했다. 그 이유는</p>
<ul>
<li>어지간한 IDE는 VIM 플러그인을 지원한다. 따라서 VIM 단축키만 익히면 다른 IDE의 단축키를 익히지 않아도 비슷한 숙련도로 단축키를 사용할 수 있다.<ul>
<li>JAVA의 모토가 Write Once, Run Everywhere 인 것처럼</li>
<li>VIM을 익히면 Learn Once, Use Shortcuts Everywhere 가 가능할 것 같다.</li>
</ul>
</li>
<li>개발을 하다보면 VIM으로만 작업이 가능한 상황을 만날 수 있다.<ul>
<li>아무리 극악의 환경이라도, 최소한 vi는 동작한다.</li>
</ul>
</li>
<li>과학적으로 증명하는 것은 아주 어렵겠지만, VIM이 러닝커브가 높지만 그에 따른 보상도 높다는 것이 VIM 사용자들의 주장으로 여기저기서 검색되었고 내가 보기엔 맞는 말로 보였다.</li>
</ul>
<p>그런데 &quot;나는 왜 몇 년간 개기면서 VIM을 익히지 않았는가?&quot; 에 대한 핑계로 요즘 나오는 키보드는 과거에 발명된 VIM을 사용하기엔 불편하다는 논리를 찾아냈다.</p>
<p>그래서 해피해킹을 질렀다. </p>
<p>VIM 쓰던가 아니면 자괴감 느끼면서 당근마켓에 키보드 팝니다를 올리던가...</p>
<h1 id="그동안-사용했던-키보드">그동안 사용했던 키보드</h1>
<p>내가 일평생 구매한 2만원 이상의 키보드는 딱 4가지이다.
이러이러한 키보드를 사용했던 사람이 쓴 후기라고 감안하고 읽으면 도움이 되겠다 싶어서 그동안 사용한 키보드들에 대해서 간단히 작성하여 보았다.</p>
<ul>
<li>스카이디지탈 기계식</li>
</ul>
<p>기계식 키보드가 온동네 PC방에 싹 깔리고 난 후에 구매했다. 청축을 사용했었는데 키감은 딱 청축 키감(조용한 곳에서 사용하면 천둥번개 치는 느낌)이였고 2~3년 차에 몇몇 키가 고장나서 다른 키보드로 갈아 탔다.</p>
<ul>
<li>한성 무접점 89</li>
</ul>
<p>기계식은 한 번 써봤고 또 뭐가 있나 검색하던 차에 &quot;무접점&quot;이라는 것의 존재를 알게 되었다. 호기심이 많은지라 여기저기 검색을 해 봤는데 내 눈에 해피해킹만 들어왔다. 하지만 그 당시에는 돈도 돈이고 개발하던 시기도 아니여서 가성비 제품을 찾다가 한성의 89키 무점접 키보드를 구매했다.</p>
<p>타건감은 기계식과는 다른 묘한 맛이였다. 다만 역시 무접점을 최대한 저렴하게 뽑아낸 제품이라 마감이 아쉬웠는데 특히 스페이스바 누를 때마다 &quot;팅~!&quot; 거리는 싸구려 스프링 소리가 아주 거슬렸다. 아직도 가끔 꺼내서 쓴다. &quot;보글보글&quot; 거리는 느낌이 나름 치는 맛이 있다. 다만 해피해킹 대비 오래 사용하면 손가락에 피로감이 좀 있다.</p>
<p>이 키보드는 자체적으로 Tab키와 CapsLock의 기능을 바꿔주는 아주 훌륭한기능이 있다. 이 때 처음 CapsLock이   쓸데 없이 아주 좋은 위치를 차지하고 있다는 것을 손가락으로 알았다. 이게 글로 읽으면 감이 안오는데, 일단 손가락이 CapsLock 위치에 Tap이 오는 구조에 적응하면 생산성이 극적으로 향상된다.</p>
<ul>
<li>한성 무접점 108</li>
</ul>
<p>집에 상시 가동하는 컴퓨터가 한 대 더 늘어나서 구매했다. 그런데 얼마 안가 한 번 떨궈짐을 당하고 나서 스페이스바 사망으로 폐기했다. 그 뒤로 집에 쓰는 컴퓨터는 그냥 멤브레인 사용한다.</p>
<ul>
<li>해피해킹 Professional HYBRID Type-S
현재 사용중</li>
</ul>
<h1 id="장점">장점</h1>
<hr>
<p>해피해킹 키보드을 사용해서 생산성이 극적으로 향성되거나 하지는 않는 것 같다. 생산성이 좋아지는 부분도 있고 오히려 떨어지는 부분도 있는 것 같다. 개발자라면 그리고 VIM을 쓴다면 전체적으로는 생산성 향상되는 부분이 더 큰 것 같긴 하다.(어디까지나 개인적인 기준이다. 내가 아직 해피해킹 키보드를 제대로 활용하지 못하는 것일 수도...) </p>
<p>그런데 이거 하나는 확실하다. 해피해킹 키보드를 쓰다가 다른 키보드를 쓰면 효율이 극악으로 떨어진다. 그리고 내가 그동안 참 피곤하게 타이핑을 해왔구나라는 생각을 하게된다. 만약 누군가에게 내가 코딩을 가르쳐야 한다면 일단 키보드부터 바꾸라고 말할 것 같다.</p>
<h2 id="타건감">타건감</h2>
<p>나는 키보드 매니아는 아니고 사용해본 키보드의 종류도 몇 가지 없다. 그리고 타건감이라는 것이 아주 주관적인 영역이라 누구에겐 아주 좋은 타건감이 누구에겐 이상한 타건감일 수도 있다.</p>
<p>개인적으론 타건 잡음만 처리하면 아주 좋다고 생각한다. 그냥 사용하면 이게 40만원짜리 키보드가 맞나 싶은 싸구려 플라스틱 자글거리는 소리가 은근히 들이는데 엄청 거슬렸다. 글의 후반부에 자글거리는 소리 해결 방법에 대해서 작성했다.</p>
<p>Type-S는 키압이 상대적으로 일반버전보다 낮은 것으로 알고 있다. HHKB 특유의 초콜릿 부서뜨리는 느낌이라는 그 쫄깃한 키감은 덜한 것 같지만, 손가락에 오는 피로가 적어서 만족하면서 사용중이다.</p>
<h2 id="키배열좋은-부분">키배열(좋은 부분)</h2>
<p>애초에 목적이 Unix 계열 시스템에 최적화된 키보드이다. 개인적으로 IDE에 Vim 플러그인 붙여서 사용하는 걸 좋아하기에 아주 만족하면서 사용중이다. VIM 쓰기엔 참 좋은 물건이다.</p>
<h3 id="control-키">Control 키</h3>
<p>해피해킹의 장점으로 가장 많이 거론되는 것 중에 하나가 CapsLock 키의 위치에 Control 키가 위치한다는 점이다. 나는 해피해킹 이전에도 CapsLcok 키의 위치에 Control 키를 매핑시켜서 사용했기에 이 장점은 이미 잘 알고 있었다. 이것만 바꿔줘도 삶의 질이 달라진다. 손이 적응하는 시간은 오래 걸리지 않는데 비해 얻는 생산성이 매우 좋다. CapsLcok + C / V 하면 타이핑 중에 검지손가락만 까딱거리면 된다. 반면에 Control + C / V 하면 손목이 공중에 한 번  떴다가 원래 타이핑 하던 위치로 와야 한다. 아주 귀찮다.</p>
<h3 id="esc-키">ESC 키</h3>
<p>Control 키 다음으로 효율이 좋다고 생각한 부분은 ESC 키의 위치이다. 해피해킹은 기존의 (<del>) 키 위치에 ESC 키가 위치하며 (</del>) 키는 최상단 최우측 으로 보내버렸다. ESC 키의 위치가 바뀌면서 ESC키 역시 타이핑 중에 손목을 움직이지 않고 누를 수 있다. 이 키 배치 역시 활용도가 매우 좋다.   </p>
<p>ESC 키는 평범한 사람이 윈도우 환경에서 컴퓨터를 사용할 때에도 자주 사용하는 키이다.  그런데 VIM을 사용하는 경우에는 활용도가 더욱 좋다. VIM을 사용하면 mode 전환을 아주 빈번하게 해야하는데 이 때 mode 를 전환하는 키가 ESC이다. 해피해킹을 사용하면 ESC 키로 모드 전환을 손목의 이동 없이 할 수 있다. 정말 효율적이다.(mode 전환을 ESC 키 말고 다른 키에 매핑시키는 방법도 있긴 하다.)</p>
<h2 id="블루투스-전환">블루투스 전환</h2>
<p>블루투스 전환이 기능이 정말 좋다!
<code>Fn</code> + <code>Control</code> + 숫자키(1~4) 조합으로 최대 4대의 디바이스를 블루투스 등록할 수 있다. 모바일 디바이스(안드로이드 폰, 태블릿 등)도 가능하다. 나는 노트북, 스마트폰, 태블릿 요렇게 3개 등록해 놓고 사용하는데 버튼 한 번 눌러서 바로 디바이스가 전환되어 아주 만족하면서 사용중이다.</p>
<h1 id="단점">단점</h1>
<hr>
<h2 id="미친-가격">미친 가격</h2>
<p>키보드 하나에 40만원(Professional HYBRID Type-S Bluetooth 모델 기준)이다. 사람에 따라서는 이 이유 하나만으로 이 키보드를 안사야될 이유는 충분하다고 본다.</p>
<h2 id="키배열구린-부분">키배열(구린 부분)</h2>
<p>방향키 위치가 특히 구리다. 가격 다음으로 이 키보드의 구린 부분이라고 생각한다. 원래 Unix에 최적화된 녀석이라 아예 일반적인 방향키는 없애버린 것까지는 이해한다. 그런데 어쩔 수 없이 기존의 방향키를 사용해야만 하는 경우가 있어서 <code>Fn</code>키 조합으로 방향키를 사용할 수 있도록은 해 놓았다. 그런데 그 배치가 아주 구리다. &quot;그냥 어쩔 수 없을 때 가끔 써&quot;라는 느낌으로 만들었다는 건 이해하는데... 배치가 너무 구리다. 지금은 많이 익숙해진 편이긴 한데 아직도 가끔 삑사리나서 오타를 친다...</p>
<h2 id="타건-잡음">타건 잡음</h2>
<p>40만원 돈을 쓴 것에 비해 타건음에 잡소리가 많이 거슬린다. 1~2 만원하는 키보드에서 날법한 플라스틱 자글 거리는 소리가 대놓고는 아니지만 은근히 들린다.</p>
<p>이 문제에는 해결 방안이 몇가지 있다. </p>
<h3 id="타건-잡음-개선-방법-1-이어폰-착용">타건 잡음 개선 방법 1: 이어폰 착용</h3>
<p>어느 날 이어폰으로 베이스 빠방한 음악(밖에 소리가 거의 안들린다.)을 들이면서 타이핑을 하는데 &quot;이 키보드가 내가 알던 그 키보드가 맞나?&quot; 싶은 탄건감이였다. 이어폰을 빼고 타이핑 해보니 내가 아는 그 키보드였다. </p>
<p>과일맛 유우의 원리가 우유에 단맛과 과일향을 첨가하여 인간이 과일 맛이 난다고 느끼게 된다는 것으로 알고 있다. 비슷하게 키보드 잡음이 전혀 들이지 않고 해피해킹의 쫄깃한 키감만 남으니 타건감이 극적으로 개선된 느낌을 받게 된 것이였다.</p>
<h3 id="타건-잡음-개선-방법-2-키보드-밑에-수건-깔기">타건 잡음 개선 방법 2: 키보드 밑에 수건 깔기</h3>
<p>키보드 밑에 수건을 깔면 잡음이 놀랍도록 샥 줄어든다. 그런데 이렇게 하면 번거롭기도하고 모냥도 많이 빠진다....</p>
<h3 id="타건-잡음-개선-방법-3-전용-흡진-매트-사용">타건 잡음 개선 방법 3: 전용 흡진 매트 사용</h3>
<p><img src="https://images.velog.io/images/full_accel/post/98c5a272-68e8-48c5-8bec-20ea71fc4fe2/image.png" alt=""></p>
<p>키보드 밑에 붙여서 잡진동을 잡는 요런 <a href="https://www.coupang.com/vp/products/2275291571?itemId=3904114543&amp;vendorItemId=71888692944&amp;q=HHKB+%ED%9D%A1%EC%A7%84+%EB%A7%A4%ED%8A%B8&amp;itemsCount=7&amp;searchId=2126fde7c7e840749712515c489c182c&amp;rank=2&amp;isAddedCart=">신박한 제품</a>이 있다. 가격은 4~5만원 정도... 비싸다. 그리고 실사용을 안해봐서 효과가 어느 정도인지는 모르겠다.</p>
<h3 id="타건-잡음-개선-방법-4-다이소에서-가구-흡진-패드-사다-붙이기">타건 잡음 개선 방법 4: 다이소에서 가구 흡진 패드 사다 붙이기</h3>
<p><img src="https://images.velog.io/images/full_accel/post/e76c9cb8-66ea-4265-b921-2541bb625ebc/image.png" alt=""></p>
<p>가구 끌릴 때 장판찍히지 말고 소음 나지 말라고 가구 밑에 붙이는 패드가 있다. 다이소 같은데서 판매한다.(싸다.) 요걸 사다가 아래처럼 붙여준다.</p>
<p><img src="https://images.velog.io/images/full_accel/post/a5f94105-762b-498d-8433-4d55995953df/%ED%95%B4%ED%94%BC%ED%95%B4%ED%82%B9%20%ED%9B%84%EB%A9%B4.jpg" alt=""></p>
<p>(붙이고 좀 지나서 때가 껴서 꼬질하다.)</p>
<p>이렇게 하면 싸구려 플라스틱 잡음이 확 줄어들어서 타건음이 깔끔해진다! 돈도 얼마 안든다! 대신에 키보드 후면 모양대로 패드를 잘라서 붙여야 하기 때문에 몸과 마음이 좀 수고로와지는 단점이 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[독후감: 리눅스 * 그냥 재미로]]></title>
            <link>https://velog.io/@full_accel/%EB%8F%85%ED%9B%84%EA%B0%90-%EB%A6%AC%EB%88%85%EC%8A%A4-%EA%B7%B8%EB%83%A5-%EC%9E%AC%EB%AF%B8%EB%A1%9C</link>
            <guid>https://velog.io/@full_accel/%EB%8F%85%ED%9B%84%EA%B0%90-%EB%A6%AC%EB%88%85%EC%8A%A4-%EA%B7%B8%EB%83%A5-%EC%9E%AC%EB%AF%B8%EB%A1%9C</guid>
            <pubDate>Sun, 24 Jan 2021 14:08:42 GMT</pubDate>
            <description><![CDATA[<p><strong>한 줄 요약: 리눅스 토발즈, 억세게 운이 좋은 남자(물론 실력도 좋다)</strong></p>
<p>가장 인상 깊은 구절</p>
<blockquote>
<p>리누스가 자랄 때 걱정이 이만저만이 아니였어요.
세상에 저래 가지고 어디
변변한 여자 하나 만날 수 있을까 싶어서요.
by 안나 토발즈(리누스의 어머니), 머릿말 앞 페이지</p>
</blockquote>
<hr>
<h1 id="이-책을-읽게된-계기">이 책을 읽게된 계기</h1>
<p>몇년 전에 리눅스를 개발한 리누즈 토발즈의 자서전격인 택이 있다는 말을 어디선가 주워들었었다. 그 때는 보안쪽 일을 할 때였다. 매일 쳐다보는 화면이 이 형님이 만든 리눅스 쉘이였다. 개인적으로 뭔가를 배울 때 항상 그 기원을 찾아보곤 한다. 리눅스도 그럴 요량으로 이 책에 대해서 알아보았다.</p>
<p>구글링하여 그 책의 이름이 「just for fun」이라는 것을 알게되었다. 조금 더 검색을 해보니 무려! 국내에 번역서가 있었는데 「리눅스 그냥 재미로」라는 이름으로 출판되었다는 사실을 알게되었다. 그런데 이미 절판인 상태였다...(이런 일을 몇 차례 겪은 후에 나는 일단 책이 좋아 보이면 먼저 구매를 하고 그 다음에 읽을 지 말지 결정하는 좋은(?) 버릇이 생겼다.)</p>
<p><img src="https://images.velog.io/images/full_accel/post/b4267cd9-a636-466a-b2d4-eab923941292/image.png" alt=""></p>
<p>일에 치이며 몇 년이 순식간에 지나고 &quot;지금이 아니면 언제 또 이렇게 원없이 책을 읽을 수 있을까?&quot; 싶은 시기가 나에게 찾아 왔다. 그래서 나름 독서 우선순위 큐를 만들어 보았는데, 가장 위에 올린 책이 이 책이였다. 열심히 중고서점을 뒤져서 상태가 비교적 멀쩡한 책을 구할 수 있었다.</p>
<h1 id="이-글의-방향">이 글의 방향</h1>
<p>세상에 깔리고 깔린 리누즈 토발즈 찬양글(또는 까는 글)을 쓰는게 무슨 소용이 있겠나 싶다. 책을 읽으면서 스스로 재밌다고 느낀 부분에 대해서 내 관점으로 정리한 기록을 남기고자 한다.</p>
<h1 id="리누즈-토발즈는-어떤-양반인가">리누즈 토발즈는 어떤 양반인가?</h1>
<p>내 언어로 풀어 써 보자면
<strong>initial D의 후지와라 타쿠미</strong>처럼 영재 교육을 받았고 <strong>Slam Dunk의 강백호</strong>와 같은 환경에서 성장한 양반. 어떤 분야의 전문가가 되기 위한 환경이 이 보다 더 좋을 수 있나 싶다.</p>
<h2 id="외할아버지-무릎-위에서-cs-영재교육">외할아버지 무릎 위에서 CS 영재교육</h2>
<p><img src="https://images.velog.io/images/full_accel/post/8543935f-e94b-4105-820c-cbbc9ccd9965/initial%20d%20water%20cup%20gif.gif" alt=""></p>
<p>Initail D는 레이싱을 소재로한 애니메이션이다. 주인공인 후지와라 타쿠미의 아버지는 한 때 악세레다 좀 밟으시던 분이였으나, 현재는 얌전하게 두부집을 운영하고 있다. 타쿠미는
(녹색 위키 인용) 강제적으로 집안일을 거들기 위해 중1때부터(!) AE86을 타고 아키나를 오르내리며 두부 배달을 해 온 이니셜 D의 주인공. (생략...) 올라갈 때는 두부를 깨지 않기 위해 물컵을 엎지르지 않으면서 빠르게 운전하고, 내려올 때는 조금이라도 빨리 집에 가고 싶어서(…) 속도를 내면서 내려오던 일이 어느새 최고의 테크니션으로 발전하게 되었다.</p>
<p>리누스의 외할아버지 레오 발데마 톤비스트(Leo Waldemar Tronqvist)는 헬싱킹 대학의 통계학 교수였다. </p>
<p>리누스는 어려서부터 외할아버지의 구식 계산기로 여러 무작위 숫자의 사인값을 구하며 엄청 재미난 시간을 보내곤 했단다...</p>
<p>리누스가 열한 살 무렵이던 1981년에 신형 코모도어 VIC-20을 구입했다고 한다.</p>
<p><img src="https://images.velog.io/images/full_accel/post/dc3bceab-260e-45de-8a5f-a1ff0d286e56/image.png" alt=""></p>
<p>코모도어 VIC-20은 가정용 완제품으로 나온 최초의 컴퓨터였다. 십대 초반의 리누스는 무려 1981년도에 그 컴퓨터에 접근할 수 있었다. 그냥 접근할 수 있었던 것이 아니라, 무려 핀란드 대학 탑티어어를 찍는 헬싱키 대학교의 통계학과 교수님이였던 외할아버지의 무릎 위에 앉아서 명령어 하나하나 영재교육을 받았다.</p>
<pre><code>10 PRINT &quot;HELLO&quot;
20 GOTO 10</code></pre><p>이런걸 1980년대에 치고 노셨다고 한다.</p>
<h2 id="적당히-경쟁적이고-적당히-지원받는-환경">적당히 경쟁적이고 적당히 지원받는 환경</h2>
<p><img src="https://images.velog.io/images/full_accel/post/c8432a66-b232-489b-aa99-ea1591d79837/image.png" alt=""></p>
<p>「위험한 심리학」은 군대에서 재미있게 읽은 책이다. </p>
<p><img src="https://images.velog.io/images/full_accel/post/1b4c7c9b-2f67-4005-b5b7-aa112711a04e/image.png" alt=""></p>
<p>무한도전에 정신분석 특집에 나왔던 저 긴머리 아저씨가 쓴 책이다.</p>
<p>가장 기억에 남는 내용은 슬램 덩크의 주인공인 강백호가 겪은 청소년기가 아주 유익한 환경이라는 설명이였다. 적당히 라이벌이 있고, 도전할 과제가 있고, 주변에 지원해주는 사람들이 있는 그런 환경이 성장하기엔 아주 좋은 조건이라는 설명이였다.</p>
<p>리누즈 토발즈의 주변 환경도 비슷하지 않았나 싶다. 리눅스가 어느정도 뜬 후에 미닉스를 개발한 타넨바움 교수랑 투닥투닥하는 과정에서 더욱 성장했을 것 같다. 추가적으로 여동생이 영어를 잘하길래 자기도 잘하려고 했다고 한다. </p>
<p>강백호 주변에 좋은 친구들과 감독님이 있었듯이 리누즈 주변에는 이메일 그룹에서 support해주던 개발자들과 linux 배포에 학교 시스템을 사용하도록 허락해준 학과의 조교님이 있었다.</p>
<h2 id="기만자-리누스-토발즈">기만자 리누스 토발즈</h2>
<p>내 주변에 무려 워싱턴대에서 Physics를 전공한 개발자가 있다. 인성 훌륭한 것은 물론이고 개발력도 아주 뛰어나서 꼭 같이 일해보고 싶은 개발자이다. 그런데 어느순간부터 이양반이 나한테 (나는 아무것도 잘못한 것이 없다.) &quot;정말 실망입니다. 당신은 기만자입니다.&quot;라면서 기만자라고 부르기 시작했다. </p>
<p>그 이유는 내가 하는 짓(개발할 때 모니터 3대를 사용, 노트북 받침대와 포터블 모니터를 항상 들고 다녀서 어디서나 최소 모니터 2대 사용, 방향키도 없는 키 60개 짜리 해괴한 키보드 사용, vscode에도 VIM plugin을 붙여서 사용, 터미널에서 뭐 하는 거 좋아함, 마우스 싫어함)을 보고 코딩이랑 결혼할 것이라 생각했는데 여자친구가 있다는 것이였다.</p>
<p>이 글의 제일 처음에서 밝혔듯이 리누스의 어머니는 &quot;세상에 저래 가지고 어디 변변한 여자 하나 만날 수 있을까?&quot;하고 걱정하셨다.</p>
<p>결론적으로 기적(리누스 어머니의 표현)이 일어났다. 기적이 어떻게 일어났냐?
핀란드는 교육시스템이 특이해서 리누스가 원치 않아도 대학에서 조교로서 수업을 할 수밖에 없는 상황이 되었다고 한다. 그 당시에 리누스가 학생들에게 내준 과제는 자기(리누스)에게 이메일 보내기 였다고 한다.(당시는 이메일 자체가 최첨단 기술이였다.) 그런데 다른 학생들은 그냥 과제를 했는데, 한 여학생은 이메일로 데이트 신청을 했다고 한다. 그 분이 현 리누스 토발즈의 부인이신 라나 토르발스이시다. 그렇게 쉽게 여자친구를 사귀셨다고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[생활코딩] JavaScript Immutability - 3. 객체를 불변하게 만들기 (Object.freeze)]]></title>
            <link>https://velog.io/@full_accel/%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9-JavaScript-Immutability-3.-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EB%B6%88%EB%B3%80%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0-Object.freeze</link>
            <guid>https://velog.io/@full_accel/%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9-JavaScript-Immutability-3.-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EB%B6%88%EB%B3%80%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0-Object.freeze</guid>
            <pubDate>Sun, 17 Jan 2021 14:48:29 GMT</pubDate>
            <description><![CDATA[<p>생활코딩의 <a href="https://www.opentutorials.org/module/4075">JavaScript Immutability</a> 강의를 정리하여 작성한 내용입니다.</p>
<hr>
<h1 id="3-객체를-불변하게-만들기-objectfreeze">3. 객체를 불변하게 만들기 (Object.freeze)</h1>
<h2 id="3-1-object-freeze로-객체를-불변하게-만들기">3-1. Object freeze로 객체를 불변하게 만들기</h2>
<p>한 번 freeze된 객체는 freeze를 해제할 수 없다. 굳이 freeze를 해동하려면 원본 객체를 복제하여 다른 변수에 할당하여야 한다.</p>
<p>그런데 역시 JavaScript 답게 freeze도 허술한 구석이 있다. freeze는 객체의 프로퍼티를 얼린다. 정확히는 객체의 프로퍼티의 추가 삭제가 불가하며 primitive 타입의 값을 변경할 수 없다. 즉, 프로퍼티의 값이 객체인 경우 그 객체는 여전히 변경 가능하다. 왜냐하면 객체의 프로퍼티는 프로퍼티에 담긴 값이 객체인 경우 객체 자체가 아니라 객체가 저장된 메모리의 주소를 참조하기 때문이다. 따라서 프로퍼티가 참조하는 메모리 주소의 객체에 직접 접근하여 수정하면 프로퍼티의 값도 바뀐다.</p>
<pre><code class="language-jsx">var o1 = { name:&#39;kim&#39;, score:[1,2] };
Object.freeze(o1); // 원본 객체를 freeze!

o1.city = &#39;seoul&#39;; // 원본 객체에 새로운 프로퍼티 추가 시도
o1.name = &#39;lee&#39;; // 원복 객체의 프로퍼티의 값(primitive 타입)을 수정 시도

// o1을 확인해 보면 위의 시도들이 전부 반영되지 않음을 알 수 있다.
console.log(o1); // {name: &#39;kim&#39;, score [1, 2]

// 하지만 원본 객체의 프로퍼티에 담긴 객체에 직접 접근하여 수정하는 방법은 여전히 가능하다.
o1.score.push(3);
console.log(o1); // {name: &#39;kim&#39;, score [1, 2, 3]</code></pre>
<p>freeze를 이용하여 원본 객체의 프로퍼티의 값이 객체인 경우에도 수정불가능하도록 하려면  프로퍼티까지 freeze해야 한다.</p>
<pre><code class="language-jsx">var o1 = { name:&#39;kim&#39;, score:[1,2] };
Object.freeze(o1); // 원본 객체를 freeze!
Object.freeze(o1.score); // 원본 객체의 프로퍼티를 freeze!

o1.city = &#39;seoul&#39;; // 원본 객체에 새로운 프로퍼티 추가 시도
o1.name = &#39;lee&#39;; // 원복 객체의 프로퍼티의 값(primitive 타입)을 수정 시도

o1.score.push(3); // 원복 객체의 프로퍼티의 값(object 타입)을 수정 시도
// -&gt; 이부분에서 아예 에러가 발생한다!
// Uncaught TypeError: Cannot add property 2, object is not extensible</code></pre>
<h2 id="3-2-const-vs-object-freeze">3-2. const vs object freeze</h2>
<p>const는 한 번 값이 할당된 변수에 다른 값을 할당하지 못하도록 한다.</p>
<p>Object.freeze()는 객체의 프로퍼티의 수정을 막는다.</p>
<pre><code class="language-jsx">const o1 = {name:&#39;kim&#39;}; // 변수를 const로 선언
const o2 = {name:&#39;lee&#39;};

Object.freeze(o1); // 객체가 담긴 변수 o1을 freeze

o1.name = &#39;kim&#39;; // freeze에 의해 변경되지 않음
console.log(o1); // {name: &quot;kim&quot;}

o1 = o2; // const에 의해 에러 발생
// Uncaught TypeError: Assignment to constant variable.</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[생활코딩] JavaScript Immutability - 2. 불변의 함수]]></title>
            <link>https://velog.io/@full_accel/JavaScript-Immutability-2.-%EB%B6%88%EB%B3%80%EC%9D%98-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@full_accel/JavaScript-Immutability-2.-%EB%B6%88%EB%B3%80%EC%9D%98-%ED%95%A8%EC%88%98</guid>
            <pubDate>Sun, 17 Jan 2021 14:45:30 GMT</pubDate>
            <description><![CDATA[<p>생활코딩의 <a href="https://www.opentutorials.org/module/4075">JavaScript Immutability</a> 강의를 정리하여 작성한 내용입니다.</p>
<hr>
<h1 id="2-불변의-함수">2. 불변의 함수</h1>
<h2 id="2-1-불변의-함수-만들기">2-1. 불변의 함수 만들기</h2>
<p>JacaScript의 함수는 파라미터의 인자가 원시 데이터 타입인 경우와 객체인 경우 그 동작방법이 달라진다.</p>
<p>객체가 함수의 인자로 전달되어, 객체 자신(원본)의 프로퍼티의 값(primitive 타입, string)이 변경되는 경우:</p>
<pre><code class="language-jsx">function fn(person){
    person.name = &#39;lee&#39;;
}
var o1 = {name:&#39;kim&#39;};
fn(o1);
console.log(o1); // {name: &quot;lee&quot;}</code></pre>
<p>객체가 함수의 인자로 전달되어, 객체 자신(원본)의 프로퍼티의 값(primitive 타입, string)의 불변성이 유지되는 경우:</p>
<ul>
<li>함수 내부에서 인자로 전달받은 객체를 복사</li>
<li>복사한 객체의 프로퍼티를 수정</li>
<li>수정한 객체를 리턴</li>
<li>함수가 리턴한 객체를 새로운 변수에 할당하여 사용</li>
</ul>
<pre><code class="language-jsx">function fn(person){
    person = Object.assign({}, person); // 함수 내부에서 인자로 전달받은 객체를 복사
    person.name = &#39;lee&#39;; // 복사한 객체의 프로퍼티를 수정
    return person; // 수정한 객체를 리턴
}
var o1 = {name:&#39;kim&#39;};
var o2 = fn(o1); // 리턴 받은 객체를 새로운 변수에 할당
console.log(o1, o2); // {name: &quot;kim&quot;} {name: &quot;lee&quot;}</code></pre>
<p>객체가 함수의 인자로 전달되어, 객체 자신(원본)의 프로퍼티의 값(primitive 타입, string)의 불변성이 유지되는 경우2:</p>
<ul>
<li>함수에 전달된 객체를 복제하여 새로운 변수에 할당</li>
<li>새로운 변수를 함수의 인자로 전달</li>
</ul>
<pre><code class="language-jsx">function fn(person){
    person.name = &#39;lee&#39;;
}
var o1 = {name:&#39;kim&#39;};
var o2 = Object.assign({}, o1); // 원본 객체를 복제하여 새로운 변수에 할당
fn(o2); // 복제된 객체가 담긴 변수를 함수에 전달
console.log(o1, o2); // {name: &quot;kim&quot;} {name: &quot;lee&quot;}</code></pre>
<h2 id="2-2-가변과-불변-api-비교">2-2. 가변과 불변 API 비교</h2>
<p>JavaScript의 API 중에 원본을 immutable하게 처리하는 API와 mutable하게 처리하는 API를 비교하면서 &quot;4. 불변의 함수 만들기&quot;에서 살펴본 메커니즘이 실제로 현실에서 어떻게 발현되는지 ARABOZA.</p>
<p>원본 객체가 변경되는 경우</p>
<pre><code class="language-jsx">var score = [1,2,3];
score.push(4);
console.log(score); // [1, 2, 3, 4]</code></pre>
<p>원본 객체를 복제하여 원본의 불변성을 유지하는 경우</p>
<pre><code class="language-jsx">var score = [1,2,3];
// score.push(4);
var score2 = score.concat(4);
console.log(score, score2); // [1, 2, 3] [1, 2, 3, 4]</code></pre>
<p>원본 객체를 변경하는 것이 유리한 경우:</p>
<ul>
<li>수 많은 변수들이 동일한 원본 객체를 참조하고 있는데, 전부 수정해야 하는 경우</li>
</ul>
<pre><code class="language-jsx">var score = [1,2,3];
var a = score;
var b = score;
var c = score;
// 수 많은 변수들이 객체(배열) score를 참조 ...
score.push(4);
console.log(score, a, b, c); // [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4]</code></pre>
<p>원복 객체의 불변성을 유지하는 것이 유리한 경우:</p>
<ul>
<li>수 많은 변수들이 동일한 원본 객체를 참조하고 있는데, 그 값이 변경되면 안됨</li>
<li>그렇지만 원본 객체의 값을 가져다가 수정해서 사용하고자 하는 경우</li>
</ul>
<pre><code class="language-jsx">var score = [1,2,3];
var a = score;
var b = score;
var c = score;
// 수 많은 변수들이 객체(배열) score를 참조 ...
// score.push(4);
var score2 = score.concat(4);
console.log(score, score2, a, b, c); // [1, 2, 3] [1, 2, 3, 4] [1, 2, 3] [1, 2, 3]</code></pre>
<p>JavaScript에서 불변성과 성능 사이에는 trade-off 관계가 성립:</p>
<ul>
<li>원본 객체를 복제해서 사용하면 원본 객체의 불변성을 유지할 수 있다. 하지만 성능상 손해를 본다.</li>
<li>원본 객체를 그냥 수정하면 성능이 빠르다. 하지만 코드가 뜻하지 않은 동작을 할 수도 있다.</li>
</ul>
<p>결론적으로 상황에 따라서 장점을 잘 살려서 사용하여야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[생활코딩] JavaScript Immutability - 1. 변수 할당 방식 비교]]></title>
            <link>https://velog.io/@full_accel/JavaScript-Immutability</link>
            <guid>https://velog.io/@full_accel/JavaScript-Immutability</guid>
            <pubDate>Sun, 17 Jan 2021 14:29:20 GMT</pubDate>
            <description><![CDATA[<p>생활코딩의 <a href="https://www.opentutorials.org/module/4075">JavaScript Immutability</a> 강의를 정리하여 작성한 내용입니다.</p>
<hr>
<h1 id="1-변수-할당-방식-비교">1. 변수 할당 방식 비교</h1>
<p><img src="https://images.velog.io/images/full_accel/post/d3affd35-9485-4869-9976-672e6a73b3db/image.png" alt=""></p>
<ul>
<li>JavaScript의 변수는 크게 Primitive 타입과, Object 타입으로 나뒨다.</li>
<li>JavaScript 내부적으로 Primitive 타입 변수와 Object 타입 변수를 메모리에 저장하는 방식이 다르다.</li>
</ul>
<h2 id="1-1-초기-값의-비교">1-1. 초기 값의 비교</h2>
<p><code>a===b</code>에서 <code>===</code>(동등비교연산자)가 <code>true</code>를 <code>return</code>한다는 의미는 a와 b가 메모리상의 같은 공간(같은 값)을 가리킨다는 의미이다.</p>
<p><img src="https://images.velog.io/images/full_accel/post/abd50bed-6efb-47a4-b108-2e6ab636f746/image.png" alt=""></p>
<p><code>var p1 = 1</code> 에서, 재할당하는 방법을 제외하면  p1에 담긴 1을 변경할 방법은 없다.</p>
<p>반면에 
<code>var o1 = {name: &#39;kim&#39;}</code>에서, 재할당하지 않고도  <code>o1</code>에 담긴 <code>{name:&#39;kim&#39;}</code>을 변경할 수 있다.</p>
<p>→ <code>o1.name = &#39;park&#39;</code></p>
<pre><code class="language-jsx">var p1 = 1;  // primitive type
var p2 = 1;
console.log(p1, p2, p1===p2); // 1 1 true

var o1 = {name:&#39;kim&#39;};  // object
var o2 = {name:&#39;kim&#39;};
console.log(o1, o2, o1===o2); // {name: &quot;kim&quot;} {name: &quot;kim&quot;} false</code></pre>
<h2 id="1-2-객체의-가변성">1-2. 객체의 가변성</h2>
<p>새로 변수 <code>var p3 = p1</code>을 선언하면 <code>p1</code>, <code>p2</code>와 동일한 메모리상의 주소를 바라보고 결과적으로 같은 값( number 1)을 가지게 된다.</p>
<p><img src="https://images.velog.io/images/full_accel/post/19e01c33-0feb-4ac2-8bf8-451f700b7ee1/image.png" alt=""></p>
<p>변수 <code>p3</code>에 2라는 값을 재할당하면 <code>p3</code>는 이제 <code>p1</code>, <code>p2</code>와는 다른 메모리 공간을 바라보고 다른 값(number 2)를 가진다.</p>
<p><img src="https://images.velog.io/images/full_accel/post/b48662b9-0850-4fe1-a208-0a682fc53b24/image.png" alt=""></p>
<p><code>var o3 = o1</code>로, <code>var o3</code>를 선언하면서 변수 <code>o1</code>을 할당하면 <code>o3</code>는 <code>o1</code>과 동일한 메모리공간을 바라보고 동일한 값(<code>{name:&#39;kim&#39;}</code>)을 가지게 된다.</p>
<p><img src="https://images.velog.io/images/full_accel/post/ae963252-1b86-4fa4-bb2a-b4b041a77963/image.png" alt=""></p>
<p>★ 여기가 하일라이트, 심장이 쫄깃해지는 포인트</p>
<p><code>var o3 = o1</code>으로 <code>o1</code>을 할당한 변수 <code>o3</code>에 <code>.</code>(점) 찍고 접근하여 프로퍼티 <code>name</code>의 값을 <code>&#39;lee&#39;</code>로 수정하면 <code>o3</code>가 바라보고 있던 메모리공간에 담겨있는 <code>{name:&#39;kim&#39;}</code>이 <code>{name:&#39;lee&#39;}</code>로 변경된다.</p>
<p>문제는 동일한 메모리공간을 바라보고 있는 가만히 있던 변수 <code>o1</code>의 값 또한 <code>{name:&#39;lee&#39;}</code>로 변경된다는 것이다.</p>
<p><code>o1</code> 입장에서는 황당하다. 자신은 아무것도 하지 않았는데 자신의 값이 변경되었다! (더글라스 크락포드 옹께서 왜 책 제목을 「자바스크립트는 왜 그 모양일까?」로 지었는지 알 것도 같다...)</p>
<p><img src="https://images.velog.io/images/full_accel/post/8681c3a5-a939-462e-a8ca-223e7746397d/image.png" alt=""></p>
<h2 id="1-3-객체의-복사">1-3. 객체의 복사</h2>
<p>변수 <code>o1</code>이 본래 가지고 있던 값을 &quot;불변(immutable)하게 하려면 어떻게 해야 하는가?
→ <code>o1</code>의 값을 복사하여 그 값을 다른 변수에 할당한다.</p>
<p><img src="https://images.velog.io/images/full_accel/post/57afa386-193d-4f16-be0f-cc6e6da9bf96/image.png" alt=""></p>
<pre><code class="language-jsx">var o1 = {name:&#39;kim&#39;};
var o2 = Object.assign({}, o1); // 간단한 Object.assign 사용법 참조
o2.name = &#39;lee&#39;;
console.log(o1, o2, o1 === o2); // {name: &quot;kim&quot;} {name: &quot;lee&quot;} false</code></pre>
<p>간단한 <code>Object.assign</code> 사용법</p>
<p><code>Object.assign(target, ...sources)</code></p>
<ul>
<li>target: 대상 객체, 리턴될 객체</li>
<li>sources: 하나 이상의 출처 객체, 대상 객체와 합쳐질 객체</li>
<li>반환 값: target(대상 객체)</li>
</ul>
<pre><code class="language-jsx">const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };

const returnedTarget = Object.assign(target, source1, source2);

console.log(&quot;target: &quot;, target);  // target:  {a: 1, b: 2, c: 3}

console.log(&quot;returnedTarget: &quot;, returnedTarget);  // returnedTarget:  {a: 1, b: 2, c: 3}</code></pre>
<p>참조</p>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">MDN web docs: Object.assign()</a></p>
<h2 id="1-4-중첩된-객체의-복사">1-4. 중첩된 객체의 복사</h2>
<p><strong>Nested object</strong></p>
<p>객체는 프로퍼티로 구성되어 있는데, 그 프로퍼티의 값 중 하나 이상이 객체인 경우 발생할 수 있는 문제.</p>
<p><code>var o1 = { name:&#39;kim&#39;, score:[1, 2] }</code> 로 변수 <code>var o1</code>의 프로퍼티 name에 primitive 타입인 문자를 담고, 프로퍼티 score에 object 타입인 배열 [1, 2]를 담은경우:</p>
<ul>
<li>메모리 공간에 { name:&#39;kim&#39;, score: (배열 [1, 2]가 저장된 메모리 주소) } 가 저장된다.</li>
<li>primitive 타입인 문자열을 담은 프로퍼티는 변수 var o1이 바라보는 메모리에 바로 저장된다.</li>
<li>object 타입인 배열을 담은 프로퍼티에 실제로 담긴 것은 배열 자체가 아닌 <strong>배열이 저장된 다른 메모리 공간의 주소</strong>이다. 프로퍼티는 이 주소를 <strong>&quot;참조&quot;</strong>한다.</li>
</ul>
<p><img src="https://images.velog.io/images/full_accel/post/cc26b290-cd56-4cba-bec3-3560307afc21/image.png" alt=""></p>
<p>변수 <code>var o1</code>의 값을 변수 <code>var o2</code>에서도 사용하고자 <code>Object.assign()</code>으로 <code>o2</code>에 할당한 경우:</p>
<ul>
<li><code>var o2 = Object.assign({}, o1)</code></li>
<li>o2가 바로보는 메모리 공간에 o1에 저장되어 있던 값인<br><code>{ name:&#39;kim&#39;, score: (배열 [1, 2]가 저장된 메모리 주소) }</code>가 그대로 복사 된다.</li>
<li>변수 <code>var o2</code>에 할당된 객체의 프로퍼티 score는 배열 <code>[1, 2]</code>에 대해서 변수 <code>var o1</code>에 할당된 객체의 프로퍼티 score가 참조하고 있는 메모리 주소를 참조하고 있다.</li>
<li>즉, 개발자는 복사를 의도하였지만 배열 [1, 2]는 메모리 상에 하나만 존재하는 상태</li>
<li>변수 <code>var o2</code>에서 .(점) 찍고 <code>score</code> 프로퍼티에 접근하여 값을 변경하면 변수 <code>var o1</code>의 <code>score</code> 프로퍼티의 값도 변경된다.</li>
</ul>
<p><img src="https://images.velog.io/images/full_accel/post/23f4755a-be3d-475d-abd1-5f3f9bd94f95/image.png" alt=""></p>
<p><code>o2.score.psuh(3)</code> 으로 변수 <code>var o2</code>의 프로퍼티 <code>score</code>의 값을 변경하여 가만히 있던 변수 <code>var o1</code>의 프로퍼티 <code>score</code>의 값이 변경되는 경우</p>
<p><img src="https://images.velog.io/images/full_accel/post/d0c37c5b-5a81-4b30-a029-e1b5ebddaf8e/image.png" alt=""></p>
<p>복제하려는 객체의 프로퍼티 값 중에 객체가 있고, 복제된 객체의 수정으로 원본객체의 수정이 발생하지 않게 하려면(즉, 원본 객체의 불변성을 유지하려면) 복제 대상 객체의 프로퍼티의 객체 또한 복제를 해야 한다.</p>
<p><img src="https://images.velog.io/images/full_accel/post/98ecc579-5aa3-4366-bbe1-19d09dcf62cc/image.png" alt=""></p>
<p>o2.score = o2.score.concat() 으로 프로퍼티 score의 값인 배열까지 복제를 하면 o2.score.push(3)로 프로퍼티 score의 값을 변경하여도 변수 var o1의 프로퍼티 score의 값에는 영향이 없다.(원본이 불변이다, 원본이 immutable 하다.)</p>
<p><img src="https://images.velog.io/images/full_accel/post/849b6edc-d396-4ceb-b3ab-658f4c118e2f/image.png" alt=""></p>
<p>배열에 대해서 <code>Object.assign</code>을 사용하면 배열의 기능들이 사라진다. 배열의 경우에는 <code>concat()</code>, <code>slice()</code>, <code>Array.from()</code> 등 복제를 하는 명령들을 사용.</p>
<p>간단한 <code>concat</code> 사용법</p>
<p><code>concat()</code> 메서드는 인자로 주어진 배열이나 값들을 기존 배열에 합쳐서 새 배열을 반환:</p>
<ul>
<li>기존 배열을 변경하지 않음</li>
<li>추가된 새로운 배열을 반환</li>
</ul>
<pre><code class="language-jsx">const array1 = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];
const array2 = [&#39;d&#39;, &#39;e&#39;, &#39;f&#39;];
const array3 = array1.concat(array2);

console.log(array3); // [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;, &quot;f&quot;]</code></pre>
<p>참조</p>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/concat">MDN web docs: Array.prototype.concat()</a></p>
<p>객체를 복사했지만, 객체 내부의 프로퍼티가 가진 객체(배열)는 복사되지 않은 경우</p>
<pre><code class="language-jsx">var o1 = {name:&#39;kim&#39;, score:[1,2]};
var o2 = Object.assign({}, o1);
console.log(o1, o2, o1===o2, o1.score===o2.score); 
// {name: &quot;kim&quot;, score: Array(2)} {name: &quot;kim&quot;, score: Array(2)} false true</code></pre>
<p>객체 내부의 프로퍼티가 가진 객체(배열)까지 완전히 복사한 경우</p>
<pre><code class="language-jsx">var o1 = {name:&#39;kim&#39;, score:[1,2]};
var o2 = Object.assign({}, o1);
o2.score = o2.score.concat();
o2.score.push(3);
console.log(o1, o2, o1===o2, o1.score===o2.score);
// {name: &quot;kim&quot;, score: Array(2)} {name: &quot;kim&quot;, score: Array(3)} false false</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[OverTheWire: Bandit - Level 6 → Level 7]]></title>
            <link>https://velog.io/@full_accel/OverTheWire-Bandit-Level-6-Level-7-6d6cqpsb</link>
            <guid>https://velog.io/@full_accel/OverTheWire-Bandit-Level-6-Level-7-6d6cqpsb</guid>
            <pubDate>Sun, 03 Jan 2021 14:22:58 GMT</pubDate>
            <description><![CDATA[<h1 id="bandit-level-6-→-level-7---문제-원문">Bandit Level 6 → Level 7 - 문제 원문</h1>
<hr>
<p><a href="https://overthewire.org/wargames/bandit/bandit7.html">https://overthewire.org/wargames/bandit/bandit7.html</a></p>
<p>Level Goal
The password for the next level is stored somewhere on the server and has all of the following properties:</p>
<p>owned by user bandit7
owned by group bandit6
33 bytes in size
Commands you may need to solve this level
ls, cd, cat, file, du, find, grep</p>
<h1 id="해석">해석</h1>
<hr>
<ul>
<li>패스워드는 서버 어딘가에 있다.</li>
<li>패스워드는 아래의 특징을 가지고 있다.<ul>
<li>사용자 bandit7의 소유이다.</li>
<li>그룹 bandit6의 소유이다.</li>
<li>33byte의 크기이다.</li>
</ul>
</li>
</ul>
<h1 id="공략">공략</h1>
<hr>
<p>이제 슬슬 난이도가 올라간다.</p>
<h2 id="상황파악">상황파악</h2>
<pre><code class="language-bash">bandit6@bandit:~$ ls
bandit6@bandit:~$ ls -al                        [1]
total 20
drwxr-xr-x  2 root root 4096 May  7 20:14 .
drwxr-xr-x 41 root root 4096 May  7 20:14 ..
-rw-r--r--  1 root root  220 May 15  2017 .bash_logout
-rw-r--r--  1 root root 3526 May 15  2017 .bashrc
-rw-r--r--  1 root root  675 May 15  2017 .profile
bandit6@bandit:~$ cd /
bandit6@bandit:/$ ls                            [2]
bin   cgroup2  etc   initrd.img      lib    lib64   lost+found  mnt  proc        root  sbin   srv  tmp  var      vmlinuz.old
boot  dev      home  initrd.img.old  lib32  libx32  media       opt  README.txt  run   share  sys  usr  vmlinuz</code></pre>
<ul>
<li>[1] 홈 디렉토리엔 아무것도 없다.</li>
<li>[2] /(루트 디렉토리)엔 뭐가 많다.</li>
</ul>
<h2 id="해결-방법---find-명령어에-옵션을-사용">해결 방법 - find 명령어에 옵션을 사용</h2>
<pre><code class="language-bash">bandit6@bandit:/$ find / -size 33c -user bandit7 -group  bandit6    [1]
find: ‘/root’: Permission denied                    [2]
find: ‘/home/bandit28-git’: Permission denied
find: ‘/home/bandit30-git’: Permission denied
find: ‘/home/bandit5/inhere’: Permission denied
find: ‘/home/bandit27-git’: Permission denied
find: ‘/home/bandit29-git’: Permission denied
find: ‘/home/bandit31-git’: Permission denied
...</code></pre>
<ul>
<li>서버 어딘가에 있다고 했으니 최상위 경로인 <code>/</code> 에서 <code>find</code> 명령어에 위의 조건들을 다 옵션으로 걸어서 찾아보자.</li>
<li>[1] <code>find / -size 33c -user bandit7 -group  bandit6</code><ul>
<li>크기 33byte</li>
<li>사용자 bandit7이 소유하며</li>
<li>그룹 bandit6이 소유한 파일을 찾는다.</li>
</ul>
</li>
<li>[2] 그런데 여전히 뭐가 많이 나온다. 하나하나 <code>cat</code>으로 찍어 보자니 왠지 뭔가 지는 것 같고 찝찝하다.</li>
</ul>
<h2 id="해결-방법-고도화---find-명령-결과에-대해서-에러-제거하여-출력">해결 방법 고도화 - find 명령 결과에 대해서 에러 제거하여 출력</h2>
<pre><code class="language-bash">...
find: ‘/home/bandit5/inhere’: Permission denied
find: ‘/home/bandit27-git’: Permission denied
find: ‘/home/bandit29-git’: Permission denied
find: ‘/home/bandit31-git’: Permission denied
...
bandit6@bandit:/$ find / -size 33c -user bandit7 -group  bandit6 2&gt; /dev/null    [1]
/var/lib/dpkg/info/bandit7.password                        [2]
bandit6@bandit:/$ cat /var/lib/dpkg/info/bandit7.password            [3]
H??????????????????????????????</code></pre>
<ul>
<li>가만히 살펴보니 permission denied 된 것들이 많다. 얘네들을 걸러보자.</li>
<li>[1] <code>find / -size 33c -user bandit7 -group  bandit6 2&gt; /dev/null</code><ul>
<li><code>2&gt; /dev/null</code> 로 에러난 결과를 모두 거른다.</li>
</ul>
</li>
<li>[2] <code>/var/lib/dpkg/info/bandit7.password</code> 라는 생긴 것부터 패스워드스러운 파일을 찾았다.</li>
<li>[3] <code>cat</code>으로 열어보니 패스워드 같은 문자열이 보인다.</li>
</ul>
<p>다음 단계로 넘어가자
<code>ssh -p 2220 bandit7@bandit.labs.overthewire.org</code></p>
<h1 id="tmi">TMI</h1>
<hr>
<h2 id="리다이렉션">리다이렉션</h2>
<ul>
<li>리눅스는  <code>&gt;</code> 를 이용하여 출력의 방향을 지정해 줄 수 있다.</li>
<li>위에서는 출력결과의 표준 에러(2)에 대해서 그 출력의 방향을 <code>dev/null</code>로 설정하였다.</li>
<li><code>dev/null</code>은 쓰레기통(내지는 블랙홀?) 비슷한 개념으로, 여기로 날리면 그냥 사라진다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[OverTheWire: Bandit - Level 5 → Level 6]]></title>
            <link>https://velog.io/@full_accel/OverTheWire-Bandit-Level-5-Level-6-jeysxw8t</link>
            <guid>https://velog.io/@full_accel/OverTheWire-Bandit-Level-5-Level-6-jeysxw8t</guid>
            <pubDate>Sun, 03 Jan 2021 14:20:36 GMT</pubDate>
            <description><![CDATA[<h1 id="bandit-level-5-→-level-6---문제-원문">Bandit Level 5 → Level 6 - 문제 원문</h1>
<hr>
<p><a href="https://overthewire.org/wargames/bandit/bandit6.html">https://overthewire.org/wargames/bandit/bandit6.html</a></p>
<p>Level Goal
The password for the next level is stored in a file somewhere under the inhere directory and has all of the following properties:</p>
<p>human-readable
1033 bytes in size
not executable
Commands you may need to solve this level
ls, cd, cat, file, du, find</p>
<h1 id="해석">해석</h1>
<hr>
<ul>
<li>키파일은 inhere 경로 밑의 어딘가에 있다.</li>
<li>키파일은 다음의 특징을 가지고 있다.<ul>
<li>인간이 읽을 수 있다.</li>
<li>1033 byte의 크기이다.</li>
</ul>
</li>
</ul>
<h1 id="공략">공략</h1>
<hr>
<p>이번 단계는 조금 생각해야 한다.</p>
<h2 id="상황-파악">상황 파악</h2>
<pre><code class="language-bash">bandit5@bandit:~$ ls
inhere
bandit5@bandit:~$ cd inhere/                    [1]
bandit5@bandit:~/inhere$
bandit5@bandit:~/inhere$ ls -a                    [2]
.   maybehere00  maybehere02  maybehere04  maybehere06  maybehere08  maybehere10  maybehere12  maybehere14  maybehere16  maybehere18
..  maybehere01  maybehere03  maybehere05  maybehere07  maybehere09  maybehere11  maybehere13  maybehere15  maybehere17  maybehere19
bandit5@bandit:~/inhere$ cd maybehere00                [3]
bandit5@bandit:~/inhere/maybehere00$ ls -a            [4]
.  ..  -file1  .file1  -file2  .file2  -file3  .file3  spaces file1  spaces file2  spaces file3
bandit5@bandit:~/inhere/maybehere00$ cd ..
bandit5@bandit:~/inhere$ cd maybehere01
bandit5@bandit:~/inhere/maybehere01$ ls -a
.  ..  -file1  .file1  -file2  .file2  -file3  .file3  spaces file1  spaces file2  spaces file3</code></pre>
<ul>
<li>[1] inhere 경로로 이동한다.</li>
<li>[2] <code>ls -a</code>로 확인하니 뭐가 많다.</li>
<li>[3] 그 중에 하나의 경로에 들어가 본다.</li>
<li>[4] 여전히 뭐가 많다. 4단계가 그냥 커피면 5단계는 TOP이다. 이번엔 정말 파일과 경로가 많다.</li>
</ul>
<h2 id="해결-방법---find-명령어의-옵션-활용">해결 방법 - find 명령어의 옵션 활용</h2>
<pre><code class="language-bash">bandit5@bandit:~/inhere/maybehere01$ cd ..            [1]
bandit5@bandit:~/inhere$ find ./* -size 1033c            [2]
./maybehere07/.file2                        [3]
bandit5@bandit:~/inhere$ file ./maybehere07/.file2        [4]
./maybehere07/.file2: ASCII text, with very long lines
bandit5@bandit:~/inhere$
bandit5@bandit:~/inhere$ cat ./maybehere07/.file2        [5]
D??????????????????????????????              </code></pre>
<ul>
<li>[1] 일단 inhere 경로로 이동한다.</li>
<li>[2] <code>find ./* -size 1033c</code> 명령어를 입력하여 inhere 경로 밑으로 크기가 1033byte인 모든 파일을 찾는다.</li>
<li>[3] <code>./maybehere07/.file2</code> 가 확인된다.</li>
<li>[4] <code>file ./maybehere07/.file2</code> 로 찍어보니 아주 긴 라인이 포함된 ASCCI text 파일이라도 한다.</li>
<li>[5] <code>cat ./maybehere07/.file2</code>으로 열어보니 과연 긴 공백이 포함되어 있는 텍스트 파일인데 어쨋든 키로 보이는 텍스트가 있다.</li>
</ul>
<p>다음 단계로 넘어가자
<code>ssh -p 2220 bandit6@bandit.labs.overthewire.org</code></p>
<h1 id="tmi">TMI</h1>
<hr>
<h2 id="아니-이렇게-풀-생각을-어떻게-하는가">아니, 이렇게 풀 생각을 어떻게 하는가?</h2>
<p>윈도우에 익숙한 대부분의 사람들은 파일 검색할 때 이름으로나 검색해봤지 용량으로도 검색이 가능하다는 생각을 하는 것 자체가 어려운 것 같다. </p>
<p>그런데 어쨋든 bandit에서 힌트를 용량으로 줬고 그럼 구글링하면 대충 각이 나온다. 모르겠으면 어떻게 질문할지 생각해 내는 것이 이 시대의 학습의 핵심인 것 같다.
<img src="https://images.velog.io/images/full_accel/post/fba3473f-c87f-4ab5-9f19-35268e9ee6e6/image.png" alt=""></p>
<h2 id="명령어를-다-외워야-할까">명령어를 다 외워야 할까?</h2>
<p>개인적인 생각으론 영어를 잘 하려거든 영어사전의 A부터 z까지 다 외우는 것보다는 단어 하나를 알게되었을 때 그 단어를 가지고 실제 회화에 써먹어 보는 것이 훨씬 더 중요하다고 본다. </p>
<p>자주 쓰는 명령어라면 당연히 외워야 겠지만 그렇지 않은 경우 그냥 그런 명령어가 존재한다는 사실만 알고 있다가 그때 그때 검색을 잘 하는 것이 능력이라고 생각한다. 학습이라는 것도 우선순위 큐의 일종이라고 생각한다. </p>
<h1 id="참조">참조</h1>
<hr>
<ul>
<li><code>find</code> 명령어 사용법<ul>
<li><a href="https://recipes4dev.tistory.com/156">https://recipes4dev.tistory.com/156</a></li>
<li>이곳에 find 명령어의 사용법이 적절한 예시와 함께 아주 잘 안내되어 있다.</li>
<li>이 블로그는 방문할 때마다 감탄한다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[OverTheWire: Bandit - Level 0 → Level 1]]></title>
            <link>https://velog.io/@full_accel/OverTheWire-Bandit-Level-0-Level-1-o45nshz0</link>
            <guid>https://velog.io/@full_accel/OverTheWire-Bandit-Level-0-Level-1-o45nshz0</guid>
            <pubDate>Sun, 03 Jan 2021 14:16:54 GMT</pubDate>
            <description><![CDATA[<h1 id="bandit-level-0-→-level-1---문제-원문">Bandit Level 0 → Level 1 - 문제 원문</h1>
<hr>
<p><a href="https://overthewire.org/wargames/bandit/bandit1.html">https://overthewire.org/wargames/bandit/bandit1.html</a></p>
<p>Level Goal
The password for the next level is stored in a file called readme located in the home directory. Use this password to log into bandit1 using SSH. Whenever you find a password for a level, use SSH (on port 2220) to log into that level and continue the game.</p>
<p>Commands you may need to solve this level
ls, cd, cat, file, du, find</p>
<h1 id="해석">해석</h1>
<hr>
<ul>
<li>패스워드는 홈 디렉토리의 readme라는 곳에 있다.</li>
<li>패스워드를 bandit1으로 ssh 접속하기 위해 사용하라.</li>
<li>각 단계의 패스워드를 찾을 때 마다 해당 레벨에 접속하기 위해 SSH를 사용하라.</li>
</ul>
<h1 id="공략">공략</h1>
<hr>
<p>아주 쉬운 레벨이다.</p>
<pre><code class="language-bash">bandit0@bandit:~$                             [1]
bandit0@bandit:~$ ls                            [2]
readme
bandit0@bandit:~$ file readme                        [3]
readme: ASCII text
bandit0@bandit:~$ cat readme                        [4]
b??????????????????????????????
bandit0@bandit:~$
</code></pre>
<ul>
<li>[1] 홈 디렉토리에 가야하는데 bandit0@bandit:~$ 를 보니 시작부터 홈 디렉토리이다.
[2] <code>ls</code>로 확인하니 readme 파일이 있다.
[3] <code>file</code>로 찍어보니 ASCII text 파일이다.
[4] <code>cat</code>으로 열어보니 이상한 문자열이 있다. 왠지 키파일처럼 보인다.</li>
</ul>
<p>다음 단계로 넘어가자.
<code>ssh -p 2220 bandit1@bandit.labs.overthewire.org</code></p>
<h1 id="tmi">TMI</h1>
<hr>
<h2 id="home-directory">home directory</h2>
<ul>
<li>리눅스의 각 계정은 자신만의 홈 디렉토리라는 경로를 갖는다. </li>
<li>이 경로들은 <code>/home</code> 에 위치한다.</li>
<li>어느 경로에서든 <code>cd ~</code>를 입력하면 자신의 홈 디렉토리로 바로 이동한다.<ul>
<li>아래의 경우 <code>/</code>경로에서 <code>cd ~</code> 명령어를 이용하여 홈 디렉토리로 바로 이동했다.</li>
<li><code>pwd</code>(print working directory): 현재 경로 출력<pre><code class="language-bash">bandit0@bandit:~$ cd /
bandit0@bandit:/$ pwd
/
bandit0@bandit:/$ cd ~
bandit0@bandit:~$</code></pre>
</li>
</ul>
</li>
<li>아래와 같이 현재 시스템에는 bandit0부터 bandit33까지의 계정이 존재한다.<pre><code class="language-bash">bandit0@bandit:~$ cd /home
bandit0@bandit:/home$ ls
bandit0   bandit13  bandit18  bandit22  bandit27      bandit29-git  bandit31-git  bandit6
bandit1   bandit14  bandit19  bandit23  bandit27-git  bandit3       bandit32      bandit7
bandit10  bandit15  bandit2   bandit24  bandit28      bandit30      bandit33      bandit8
bandit11  bandit16  bandit20  bandit25  bandit28-git  bandit30-git  bandit4       bandit9
bandit12  bandit17  bandit21  bandit26  bandit29      bandit31      bandit5
bandit1@bandit:/home$</code></pre>
</li>
</ul>
<h2 id="ls">ls</h2>
<ul>
<li>list segment<ul>
<li>list: 목록, 명단</li>
<li>segment: 부분</li>
</ul>
</li>
<li>현재 경로에 있는 파일, 디렉토리의 목록을 출력한다.</li>
<li>윈도우의 dir 명령어에 대응한다.</li>
</ul>
<h2 id="file">file</h2>
<ul>
<li>인자로 넘겨 받은 파일이 어떤 파일인지 확인한다.</li>
<li>아래의 경우 readme 파일은 ASCII 형식의 text 파일이다.<pre><code>bandit0@bandit:~$ file readme
readme: ASCII text</code></pre></li>
</ul>
<h2 id="cat">cat</h2>
<ul>
<li>con<strong>CAT</strong>ernate: 연쇄된, 이어진, 연결된</li>
<li>인자로 넘겨 받은 파일의 내용을 바로 화면에 출력한다.</li>
<li>아래의 경우 readme 파일은 &quot;b??????????????????????????????&quot; 이라는 텍스트를 가지고 있다.(키파일 이어서 임의로 ?로 처리함)<pre><code class="language-bash">bandit0@bandit:~$ cat readme
b??????????????????????????????</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[공공기관 해킹관련 기사를 보고...]]></title>
            <link>https://velog.io/@full_accel/%EA%B3%B5%EA%B3%B5%EA%B8%B0%EA%B4%80-%ED%95%B4%ED%82%B9%EA%B4%80%EB%A0%A8-%EA%B8%B0%EC%82%AC%EB%A5%BC-%EB%B3%B4%EA%B3%A0-a0nj9lw7</link>
            <guid>https://velog.io/@full_accel/%EA%B3%B5%EA%B3%B5%EA%B8%B0%EA%B4%80-%ED%95%B4%ED%82%B9%EA%B4%80%EB%A0%A8-%EA%B8%B0%EC%82%AC%EB%A5%BC-%EB%B3%B4%EA%B3%A0-a0nj9lw7</guid>
            <pubDate>Sun, 27 Dec 2020 14:55:01 GMT</pubDate>
            <description><![CDATA[<p>&quot;해킹관련 지식이 없는 기자도 뚫을 만큼 공공기관 홈페이지의 보안이 허술하다!&quot; 라는 내용의 기사를 보았다.</p>
<p>관련 기사:
<a href="https://www.ytn.co.kr/_ln/0134_202010071353358166">https://www.ytn.co.kr/_ln/0134_202010071353358166</a>
영상 재생이 안되면 아래의 링크를 이용하세요.
<a href="https://search.naver.com/search.naver?where=nexearch&amp;sm=top_hty&amp;fbm=1&amp;ie=utf8&amp;query=%5B%EC%9E%90%EB%A7%89%EB%89%B4%EC%8A%A4%5D+&quot;%EA%B8%B0%EC%9E%90%EA%B0%80+%EC%A7%81%EC%A0%91+%ED%95%B4%ED%82%B9+%EC%84%B1%EA%B3%B5&quot;...%EB%B3%B4%EC%95%88+%ED%97%88%EC%88%A0+%EB%81%9D%ED%8C%90%EC%99%95+%ED%99%88%ED%8E%98%EC%9D%B4%EC%A7%80">https://search.naver.com/search.naver?where=nexearch&amp;sm=top_hty&amp;fbm=1&amp;ie=utf8&amp;query=[자막뉴스]+&quot;기자가+직접+해킹+성공&quot;...보안+허술+끝판왕+홈페이지</a></p>
<p>보안쪽으로 일하던 시절에, 딱 이 문제 때문에 야근을 했던 기억이 새록새록 떠올랐다. 기사를 보아하니 무언가를 비판하고자하는 강려크한(?) 욕구에 사건의 본질이 흐려지는 것 같았다. (뭔지는 잘 모르지만 일단 까고 싶다는 느낌) 추억도 돋는 김에 관련 썰을 풀면서 기사의 팩트 체크도 해보고자 한다.</p>
<hr>
<h1 id="기사의-개요">기사의 개요</h1>
<ul>
<li>대한민국 공공기관 홈페이지에 로그인할 때 입력된 아이디와 패스워드를 기자가 손쉽게 해킹(?)했다.<ul>
<li>이 때 wireshark로 스니핑한 패스워드를 보여주는데 깨알같이 <code>test1q2w3e</code> 이다.(<code>1q2w3e</code> 내지 <code>1q2w3e4r</code> 은 대한민국 국군 1급 기밀이다.)</li>
</ul>
</li>
<li>해킹관련 지식이 없는 기자도 해킹할 정도로 보안이 허술하다.</li>
<li>왜 그런고 하니 https를 적용하면 &quot;모바일로 접속할 경우 오류가 생긴다&quot;는 이유로 이를 중단했습니다고 한다. (???)
<img src="https://images.velog.io/images/full_accel/post/a099b31b-dcf7-4070-9f6a-fa4d3b4bce21/image.png" alt=""></li>
<li>아무튼 얘네들은 잘못했다.</li>
</ul>
<h1 id="기사-해설-해석">기사 해설? 해석?</h1>
<ul>
<li>전체적으로는 맞는 얘기를 하긴하는데... 뭔가 좀 애매한 것 같다...</li>
<li>무언가를 비판하고자 하는 강려크한 욕구(?) 때문에 사건의 본질리 흐려지는 것 같다.</li>
</ul>
<h2 id="기자가-사용한-프로그램wireshark은-해킹프로그램이라고-말하기엔-무리가-있다">기자가 사용한 프로그램(wireshark)은 해킹프로그램이라고 말하기엔 무리가 있다.</h2>
<p>기자가 해킹(?) 시연에 사용한 프로그램은 wireshark 라는 툴이다. 이 프로그램을 굳이 정의 내리자면 네트워크 트래픽 분석 툴이라고 보는 게 맞을 것 같다. 그냥 밑도 끝도 없이 해킹 프로그램이 아니라...</p>
<p><img src="https://images.velog.io/images/full_accel/post/69a29d5c-b2d2-47c2-a7a2-182c079527fc/image.png" alt=""></p>
<p>기사 논리대로 가면 크롬도 <code>F12</code> 누르고 네트워크 탭에 가면 네트워크 트래픽을 분석할 수 있으니 해킹 툴이 된다. 비슷한 논리로 식칼은 살인 도구이고 모든 컴퓨터는 해킹 장비이다. 오바 좀 더하면 벽돌도 건축자재가 아니라 뚝배기 깨는 흉기이다.</p>
<h2 id="왜-저런-사단이-벌어지는가">왜 저런 사단이 벌어지는가?</h2>
<ul>
<li>GPKI 인증서(행정전자서명, 행정안전부를 최상위 인증기관으로 하는 인증서)가 웹브라우저 메이커에게 제대로 인정받지 못했기 때문이다.</li>
<li>참조: <a href="https://zdnet.co.kr/view/?no=20181227003039">zdnet: 정부, 공공사이트 HTTPS &#39;보안경고&#39; 못 없앴다</a>(설명이 잘 되어 있는 기사.)</li>
</ul>
<p><img src="https://images.velog.io/images/full_accel/post/f6522913-5318-4686-8263-f4dfa390c731/image.png" alt=""></p>
<h2 id="나는-왜-야근을-했었나">나는 왜 야근을 했었나?</h2>
<ul>
<li>저 GPKI 인증서 때문에 모바일 접속시 경고 메시지가 출력되는 걸 아주 못마땅하게 생각하시던 훌륭한 마인드를 가지신 고객사의 공무원님께서 작업을 지시하셨다.</li>
<li>공무원님 말씀: GPKI 말고 외제 싸제 인증서 구매했으니 교체해 주세요.</li>
<li>공무원님 말씀 해석<ul>
<li>인증서 교체하면 어쨋거나 한 번은 서비스 끊기니까 당연히 저녁에 작업(야근)해야하는거  아시죠?</li>
<li>서비스 끊기는 작업이니까 당연히 작업계획서 써오셔야 하는거 아시죠?</li>
</ul>
</li>
</ul>
<h2 id="저-해킹은-어떻게-시연했을까">저 해킹(?)은 어떻게 시연했을까?</h2>
<ul>
<li>아마도 추측컨데 대한민국 네트워크의 말단을 장악하고 있는 i사의 장비에서 포트미러링 설정하여 모든 패킷을 스니핑하고</li>
<li>스니핑된 패킷을 wireshark로 열어봤을 것 같다.
<img src="https://images.velog.io/images/full_accel/post/283c7eef-9c0c-44eb-bbe4-297dc82f43b0/image.png" alt=""></li>
<li>i사 공유기로 클릭 몇 번하면 포트미러링이 가능하다. <ul>
<li>TMI. 제발 공유기 관리자 페이지 비밀번호를 어려운 것으로 바꾸자.<ul>
<li>그리고 그냥 잊어버리자. </li>
<li>어차피 처음 세팅하고 다시 들어올 일이 거의 없으니. </li>
<li>문제 생기면 그냥 리셋 버튼 누르고 다시 설정하면 그만이다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="포트-미러링이란">포트 미러링이란?</h3>
<p>말 그대로 특정 port(여기서는OSI 4계층의 주소인 port가 아니라, 물리적인 통신장비에 UTP 케이블이 연결되는 그 물리적인 port)로 들어가고 나오는 모든 네트워크 트래픽에 대해서 미러링(거울로 보듯이, 트래픽을 카피)하겠다는 것이다.</p>
<p>즉, 내가 특정 포트에 포트 미러링을 설정하면 해당 포르트를 지나는 모든 트래픽을 나도 받아볼 수 있게된다.</p>
<h3 id="패스워드-해킹이-가능한-이유는">패스워드 해킹이 가능한 이유는?</h3>
<p>기사에서 시연할 때 SSL(암호화)이 적용되지 않은 상태였다. 따라서 포트 미러링으로 지나가는 트래픽만 받아 보면 평문으로 된 사용자의 패스워드를 확인할 수 있다.</p>
<h2 id="그래서-결론은">그래서 결론은?</h2>
<h3 id="gpki-인증서가-해외-브라우저-제조업체에게-인정받지-못해서-발생한-사단이다">GPKI 인증서가 해외 브라우저 제조업체에게 인정받지 못해서 발생한 사단이다.</h3>
<ul>
<li>웹서비스를 안전하게 제공하기 위해서는 SSL이라는 기술을 사용해야 한다.</li>
<li>이를 위해서는 웹서버는 SSL 인증서를 탑재해야 한다.</li>
<li>그런데 이 SSL 인증서가 믿을만한가 아닌가는 전적으로 고객이 사용하는 웹브라우저가 판단한다.</li>
<li>즉, 웹서버가 SSL 인증서를 가지고 있어도 웹브라우저가 부적절한 인증서라고 판단하면 &quot;!연결이 비공개로 설정되어 있지 않습니다.&quot; 라는 무서운 화면이 출력되면서 SSL 통신이 적용되지 않는다.</li>
<li>대한민국에는 GPKI 인증서(행정전자서명, 행정안전부를 최상위 인증기관으로 하는 인증서)가 있다.</li>
<li>공공기관들이 당연히 이 인증서를 탑재했는데,</li>
<li>해외 유명 브라우저들(크롬 등)은 모바일 버전에 대해서 GPKI(행정전자서명) 인증서가 적절하지 않다고 판단했다.</li>
<li>그래서 GPKI(행정전자서명) 인증서를 탑재한 홈페이지에 접속하면 &quot;!연결이 비공개로 설정되어 있지 않습니다.&quot; 라는 무서운 화면을 보여줬고, SSL 통신을 지원하지 않았다.</li>
</ul>
<h3 id="위-기사에-나온-공공기관이-잘못했나">위 기사에 나온 공공기관이 잘못했나?</h3>
<p>당연히 잘못했다고 본다. 문제를 인지한 즉시 적절한 외산 인증서로 교체하여 모바일 브라우저의 경고창을 사용자들이 보지 않도록 했어야 했다. </p>
<p>특히 모바일에서 경고창 보여주기 싫다고 인증서 자체를 빼버렸다면... 안전벨트를 메지 않으면 차에서 자꾸 경고음이 울리니 안전벨트 자체를 없애버리는 수준의 극단적으로? 창의적인 발상을 했다고 생각한다.</p>
<h3 id="그럼-다른-부처는-잘못이-없나">그럼 다른 부처는 잘못이 없나?</h3>
<p>당연히 근본적인 문제는 GPKI(행정전자서명)에 있다고 본다. 애초에 잘 만들어서 브라우저 제조업체가 GPKI(행정전자서명) 인증서를 안전한 인증서라고 판단했으면 이런 일 자체가 발생하지 않았을 것이다. 더불어 매년마다 인증서를 갱신하면서 외국의 인증서 제조업체에 비용도 지불하지 않아도 되었을 것이다.</p>
<h1 id="3줄-요약">3줄 요약</h1>
<ol>
<li>GPKI 인증서(행정전자서명, 행정안전부를 최상위 인증기관으로 하는 인증서)가 시장 점유율이 높은 웹브라우저(크롬 등)에 제대로 인정 받지 못해서 해당 브라우저들은 GPKI인증서를 탑재한 웹서비스에서 SSL을 지원하지 않는다.</li>
<li>일부 정부 기관에서 GPKI 인증서를 자신들의 웹서비스에 적용하여서 GPKI를 인정하지 않는 브라우저들로는 해당 웹서비스에 https로 접속할 수 없었다.</li>
<li>GPKI 인증서(행정전자서명, 행정안전부를 최상위 인증기관으로 하는 인증서)가 제대로된 인증서였다면 애초에 아무 문제도 없었을 것이다.(기사에서는 이부분에 대한 언급이 없다.)</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[help 카운트 고도화 방안1]]></title>
            <link>https://velog.io/@full_accel/help-%EC%B9%B4%EC%9A%B4%ED%8A%B8-%EA%B3%A0%EB%8F%84%ED%99%94-%EB%B0%A9%EC%95%88</link>
            <guid>https://velog.io/@full_accel/help-%EC%B9%B4%EC%9A%B4%ED%8A%B8-%EA%B3%A0%EB%8F%84%ED%99%94-%EB%B0%A9%EC%95%88</guid>
            <pubDate>Sun, 27 Dec 2020 03:18:22 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[관계형 데이터베이스 - 무결성(Integrity)]]></title>
            <link>https://velog.io/@full_accel/%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EB%AC%B4%EA%B2%B0%EC%84%B1Integrity</link>
            <guid>https://velog.io/@full_accel/%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EB%AC%B4%EA%B2%B0%EC%84%B1Integrity</guid>
            <pubDate>Sun, 20 Dec 2020 02:53:04 GMT</pubDate>
            <description><![CDATA[<ul>
<li><a href="http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&amp;ejkGb=KOR&amp;barcode=9791196319229&amp;orderClick=JAj">관계형 데이터 모델링 프리미엄 가이드</a>의 CHAPTER 02 데이터 모델링 기본 개념을 바탕으로 정리한 글입니다.</li>
<li>일부 내용은 추가, 수정, 삭제되었을 수 있습니다.</li>
</ul>
<h1 id="무결성과-정합성">무결성과 정합성</h1>
<hr>
<h2 id="데이터-무결성">데이터 무결성</h2>
<ul>
<li>무결성은 데이터 값이 정확한 상태</li>
<li>Data Integrity가 주로 데이터 무결성으로 번역되나, 정확하다는 의미에서 데이터 완전성이나 정확성이라는 표현이 더 간결</li>
</ul>
<h2 id="데이터-정합성">데이터 정합성</h2>
<ul>
<li>정합성은 무결성과 유사하게 사용되는 용어</li>
<li>어떤 데이터들의 값이 서로 일치할 때 데이터 정합성이 맞다고 표현</li>
<li>중복 데이터를 많이 사용하면 데이터끼리 정합성을 맞추기 어렵고 궁극적으로는 서로 달라지는 경우(정합성이 깨지는 경우) 발생 가능</li>
<li>비정규형을 사용하여 아노말리가 발생하면 데이터 정합성이 깨진다.</li>
</ul>
<h2 id="무결성과-정합성의-비교">무결성과 정합성의 비교</h2>
<ul>
<li><strong>정합성은 데이터가 서로 모순 없이 일관되게 일치해야 한다는 의미</strong></li>
<li><strong>무결성은 데이터가 정확하고 완전해야 한다는 의미</strong> → 데이터는 제대로된(멀쩡한, 모델러나 개발자가 의도한) 상태로 존재해야 한다.</li>
<li>어떤 데이터는 정합성에는 이상이 없으나 무결성은 훼손된 상태일 수 있다.<ul>
<li>ex) 중복 데이터가 전부 동일하나 옳바르지 않은 값으로 일치하면 정합성은 만족하나 무결성은 훼손된 상태 → 특정 사용자의 주소에 전부 False 가 들어간 경우</li>
</ul>
</li>
<li>따라서 무결성의 정의가 더 넓은 개념</li>
<li>무결성을 지키는 것이 데이터 모델링의 최고의 목표</li>
</ul>
<h1 id="데이터-무결성의-종류">데이터 무결성의 종류</h1>
<hr>
<ul>
<li>관계형 데이터베이스의 가장 큰 목표는 데이터 무결성을 높이는 것</li>
<li>무결성에는 다음의 4가지 종류가 있다.<ol>
<li>엔터티 무결성(Entity Integrity)</li>
<li>참조 무결성(Referential Integrity)</li>
<li>도메인 무결성(Domain Integrity)</li>
<li>업무 무결성(Business Integrity)</li>
</ol>
</li>
</ul>
<h1 id="엔터티-무결성entity-integrity">엔터티 무결성(Entity Integrity)</h1>
<hr>
<ul>
<li>엔터티에 존재하는 모든 인스턴스는 고유해야 한다.</li>
<li>인스턴스를 대표하는 속성(Primary Key)에는 Null 값이 올 수 없다.</li>
<li>→ 엔터티에는 동일한 주 식별자가 존재할 수 없으며 주 식별자 속성은 모르는 값인 Null 값을 허용할 수 없다.
<img src="https://images.velog.io/images/full_accel/post/e127d3a4-fbf5-4e3f-b2a6-3a25633ae430/image.png" alt=""></li>
<li>두 번째 인스턴스는 첫 번째 인스턴스와 중복이므로 엔터티 무결성 위반</li>
<li>세 번째 인스턴스의 주문번호 속성은 Primary Key인데 null 이므로 엔터티 무결성 위반</li>
</ul>
<h1 id="참조-무결성referential-integrity">참조 무결성(Referential Integrity)</h1>
<hr>
<ul>
<li><p>참조 무결성: 엔터티의 왜래 식별자 속성은 참조되는 엔터티의 주 식별자 값과 일치하거나 Null 값이어야 한다.</p>
</li>
<li><p>즉 외래 식별자 속성 값이 상위 엔터티의 인스턴스에 반드시 존재하거나 Null 이어야 한다.</p>
</li>
<li><p>참조 무결성은 두 엔터티의 연관된 인스턴스 사이에 일관성을 유지하기 위한 제약으로 사용</p>
</li>
<li><p>이 제약은 관계형 데이터베이스에서 집합(엔터티) 사이에 연산할 수 있도록 하는 대단히 중요한 개념
<img src="https://images.velog.io/images/full_accel/post/cc5cbde1-a5bc-4d1e-9835-23c7014494ec/image.png" alt=""></p>
</li>
<li><p>주문 릴레이션은 고객 릴레이션을 참조하므로 주문 릴레이션의 고객번호 속성은 외래 식별자</p>
</li>
<li><p>이때 주문 릴레이션의 고객번호 속성 값은 고객 릴레이션의 주 식별자인 고객번호 속성에 존재해야 한다.</p>
</li>
<li><p>참조 무결성은 데이터 모델에서 절대적으로 필요한 중요한 요소이며 제약</p>
</li>
<li><p>참조 무결성은 FK(Foreign Key) 제약에 의해서 지켜진다.</p>
</li>
</ul>
<h1 id="도메인-무결성">도메인 무결성</h1>
<hr>
<ul>
<li>도메인 무결성은 속성 값과 관련된 제약</li>
<li>엔터티의 특정 속성 값은 동일한 데이터 타입, 길이, Null 허용 여부, 기본 값, 허용 값 등 동일한 범주의 값만이 존재해야 한다.</li>
<li>동일한 속성에 사용되는 값들은 동일한 성격의 값이 사용되어야 한다.</li>
<li>도메인 무결성 예시<ul>
<li>고객이름 속성에 &quot;Homer&quot;는 허용, 777은 불가</li>
<li>전화번호 속성에 &quot;555-5555&quot;는 허용, &quot;오오오~오오오오&quot;는 불가</li>
</ul>
</li>
<li>도메인 무결성은 기본 값, Null 허용 여부, 체크 조건 등으로 지켜질 수 있다.</li>
</ul>
<h1 id="업무-무결성">업무 무결성</h1>
<hr>
<ul>
<li>업무 무결성은 기업에서 업무를 수행하는 방법이나 데이터를 처리하는 규칙</li>
<li>넓게 보면 엔터티 무결성이나 참조 무결성, 도메인 무결성도 업무 무결성에 포함</li>
<li>업무 무결성 예시<ul>
<li>주문 금액 3만 원 이상이면 무료배송</li>
<li>초회 보험료를 입금하지 않은 보험 계약은 무효</li>
</ul>
</li>
<li>업무 무결성은 범위가 넓어 주로 프로그램(의 로직)에서 확인</li>
<li>업무 무결성을 물리적으로 강제하는 대표적인 방법에는 트리거가 존재</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[관계형 데이터베이스 - 관계형 모델의 기본 개념과 용어 정의]]></title>
            <link>https://velog.io/@full_accel/%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EA%B4%80%EA%B3%84%ED%98%95-%EB%AA%A8%EB%8D%B8%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%9A%A9%EC%96%B4-%EC%A0%95%EC%9D%98</link>
            <guid>https://velog.io/@full_accel/%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EA%B4%80%EA%B3%84%ED%98%95-%EB%AA%A8%EB%8D%B8%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%9A%A9%EC%96%B4-%EC%A0%95%EC%9D%98</guid>
            <pubDate>Sun, 20 Dec 2020 02:49:40 GMT</pubDate>
            <description><![CDATA[<ul>
<li><a href="http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&amp;ejkGb=KOR&amp;barcode=9791196319229&amp;orderClick=JAj">관계형 데이터 모델링 프리미엄 가이드</a>의 CHAPTER 02 데이터 모델링 기본 개념을 바탕으로 정리한 글입니다.</li>
<li>일부 내용은 추가, 수정, 삭제되었을 수 있습니다.</li>
</ul>
<h1 id="관계형-모델에-대한-이론적인-정의">관계형 모델에 대한 이론적인 정의</h1>
<hr>
<ul>
<li>함수 종속(Functional Dependency)에 의해 정규화(Normalization)된 모델</li>
</ul>
<h1 id="관계형-모델의-용어-정의">관계형 모델의 용어 정의</h1>
<hr>
<p><img src="https://images.velog.io/images/full_accel/post/0395def6-5ee5-442b-8f17-c5717e8da7ff/image.png" alt=""></p>
<h2 id="릴레이션">릴레이션</h2>
<ul>
<li>릴레이션(Relation): 관계형 모델에서 기초가 되는 개념</li>
<li>릴레이션은 가로와 세로로 이루어진 테이블(표) 형태의 2차원 데이터</li>
<li>머리(Head) 부분인 애트리뷰트와 몸통(Body) 부분인 튜플로 구분</li>
<li>릴레이션에는 이름이 존재하며 2차원의 테이블 형태로 데이터(Value, 애트리뷰트 값)가 관리된다.</li>
<li>각 열을 튜플(Tuple)이라 하며 각 행을 애트리뷰트(Attribute)라고 한다.</li>
<li>애트리뷰트 중에서 튜플을 유일하게 식별할 수 있는 애트리뷰트가 식별자(Identifier)</li>
<li>이름, 주소와 같은 애트리뷰트의 이름을 내포(Intension 또는 Head)라고 하며 &#39;1234&#39;, &#39;홍길동&#39; 같은 실제 데이터를 외포(Extension 또는 Body)라고 한다.</li>
<li>릴레이션의 이름과 내포를 스키마(Schema)라고도 한다.</li>
<li>릴레이션의 튜플의 개수를 카디널러티(Cardinality)라고 한다.</li>
<li>애트리뷰트의 개수를 차수(Degree)라고 한다.</li>
<li>차수가 1개 이상이고 카디널리티가 0개 이상이면 유효한 릴레이션이다.</li>
<li>튜플은 흔히 레코드(Record), 로우(Row), 인스턴스(Instance)라고도 부른다.</li>
<li>애트리뷰트는 컬럼(Column), 필드(Field)라고 부른다.</li>
</ul>
<h2 id="엔터티entity7장에서-정의됨">엔터티(Entity)[7장에서 정의됨]</h2>
<ul>
<li>엔터티에 대한 정의(엔터티가 무엇인지를 정의하는 것은 쉽고도 어렵다. )<ol>
<li>간단하게 설명하면 필요에 의해 관리하고자 하는 데이터의 집합</li>
<li>업무를 수행하는 데 필요한 데이터를 특성이 유사한 것끼리 모아 놓은 독립적인 집합</li>
<li>특성이 유사한 것끼리 모았다는 것은 함수 종속을 의미 하므로 업무에서 관리하고자 하는 데이터(속성)를 함수 종속(Functional Dependency)에 의해 도출한 결과 집합이 엔터티라고 정의할 수 있다.</li>
<li>엔터티는 &quot;사람(Person), 장소(Place), 사물(Object), 사전(Event), 개념(Concept) 등을 표현한 집합이다.&quot;라는 정의는 가장 일반적인 엔터티에 대한 정의</li>
</ol>
</li>
</ul>
<h1 id="관계형-모델의-특징">관계형 모델의 특징</h1>
<hr>
<h2 id="왜-관계형-데이터베이스라고-하나">왜 관계형 데이터베이스라고 하나?</h2>
<ul>
<li>관계형 데이터베이스(Relational Database)의 <strong>Relational</strong>은 데이터 모델의 관계(Relationship) 때문에 붙여진 이름이 아니라 <strong>릴레이션(Relation)</strong> 때문에 붙여진 이름</li>
</ul>
<h2 id="관계형-모델의-특징-1">관계형 모델의 특징</h2>
<ul>
<li>관계형 데이터베이스에는 2차원 테이블 형태의 여러 릴레이션들이 존재하고 릴레이션에는 식별자가 존재</li>
<li>식별자 중에는 외래 식별자가(Foreign Key)가 존재해 주 식별자와 조인을 통해 릴레이션 사이의 연관 관계를 관리</li>
<li>조인을 통해서 데이터를 얻을 수 있으므로 데이터 중복이 최소화되는데, <strong>데이터를 중복해서 저장하지 않도록 설계하는 것이 관계형 데이터베이스 설계의 핵심</strong></li>
</ul>
<h2 id="관계형-데이터베이스의-단점">관계형 데이터베이스의 단점</h2>
<ul>
<li>데티어 구조를 효율적으로 설계하기 어렵다는 것이 관계형 데이터베이스의 단점</li>
</ul>
<h1 id="관계형-모델이-지켜야할-제약">관계형 모델이 지켜야할 제약</h1>
<hr>
<ul>
<li>일반적으로 다음과 같은 제약(Constraints)을 만족하지 않으면 관계형 모델이 아니다.<ul>
<li>릴레이션에서 각 튜플은 유일해야 한다.(가장 기본적인 제약)</li>
<li>★ 한 릴레이션에는 하나의 데이터 주제만이 포함된어야 한다.</li>
<li>식별자의 값이 같은 튜플이 존재해서는 안 된다. → 엔터티 무결성(Entity Integrity)</li>
<li>애트리뷰트에는 유일한 값이 사용되어야 한다.(다중 값이나 복합 값이 존재해서는 안 된다.)<ul>
<li>위의 그림에서 두 번째 튜플의 취미 애트리뷰트 값은 다중 값이므로 제약 위반</li>
</ul>
</li>
<li>전체 모델에서 릴레이션의 이름은 유일해야 한다.</li>
<li>릴레이션 내에서 애트리뷰트의 이름도 유일해야 한다.<ul>
<li>가능하다면 전체 릴레이션에서 애트리뷰트의 이름이 유일한 것이 좋다.</li>
</ul>
</li>
<li>릴레이션 내에서 튜플의 차례는 중요하지 않다.(가장 나중에 입력된 튜플이 제일 처음에 있어도 된다.)</li>
<li>릴레이션에는 튜플이 존재하지 않을 수도 있다.</li>
<li>애트리뷰트의 순서도 중요하지 않다.</li>
<li>모든 릴레이션은 함수 종속 규칙을 따라야 한다.</li>
<li>릴레이션이 정규화(Normalization)되지 않으면 관계형 모델이라 할 수 없다.</li>
<li>정규화된 릴레이션 사이에는 외래 식별자(Foreign Identifier)를 통해서 연관 관계가 성립</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Django - request에 대해 .get 으로 받는 방법과 ['key']로 받는 방법의 차이]]></title>
            <link>https://velog.io/@full_accel/Django-request%EC%97%90-%EB%8C%80%ED%95%B4-.get-%EC%9C%BC%EB%A1%9C-%EB%B0%9B%EB%8A%94-%EB%B0%A9%EB%B2%95%EA%B3%BC-key%EB%A1%9C-%EB%B0%9B%EB%8A%94-%EB%B0%A9%EB%B2%95%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@full_accel/Django-request%EC%97%90-%EB%8C%80%ED%95%B4-.get-%EC%9C%BC%EB%A1%9C-%EB%B0%9B%EB%8A%94-%EB%B0%A9%EB%B2%95%EA%B3%BC-key%EB%A1%9C-%EB%B0%9B%EB%8A%94-%EB%B0%A9%EB%B2%95%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 20 Dec 2020 02:37:00 GMT</pubDate>
            <description><![CDATA[<h3 id="결론">결론</h3>
<ul>
<li>Error를 raise하냐 안하냐의 차이</li>
<li>headers에서 .get으로 받으면 Error를 raise 하지 않고 None을 리턴한다.<ul>
<li>따라서 값이 None 인 경우로 분기 처리해야 한다.</li>
</ul>
</li>
<li>header에서 [&#39;key&#39;]로 받으면 KeyError를 raise한다.<ul>
<li>따라서 try ~ except 로 KeyError를 처리해야 한다.</li>
</ul>
</li>
</ul>
<p>(예시)
프론트에서 전달받은 request의 header에서 &quot;Authorization&quot;이라는 키에 해당하는 값이 필요한 경우</p>
<h3 id="headers에서-get으로-받는-경우">headers에서 .get으로 받는 경우</h3>
<ul>
<li>heders에서 .get으로 뽑는 경우 헤더에 &#39;Authorization&#39; 이 없으면 access_token = None</li>
<li>따라서 <code>if access_token is None</code> 등의 방식으로 분기 처리해야 클라이언트에 적절한 메세지 전달 가능</li>
</ul>
<pre><code class="language-python">access_token = request.headers.get(&#39;Authorization&#39;)

if not access_token:  # access_token은 None을 리턴, python은 조건문에서 None도 False로 처리
    return JsonResponse({&quot;message&quot;: &quot;KEY_ERROR&quot;}, status=400)</code></pre>
<h3 id="headers에서-key로-받는-경우">headers에서 [&#39;key&#39;]로 받는 경우</h3>
<ul>
<li>heders에서 [&#39;key&#39;]로 뽑는 경우 헤더에 &#39;Authorization&#39; 이 없으면 KeyError가 raise된다.</li>
<li>따라서 이경우 try except 로 KeyError 받아야 클라이언트에 적절한 메세지 전달 가능</li>
</ul>
<pre><code class="language-python">try:
    access_token = request.headers[&#39;Authorization&#39;]
except KeyError:
    return JsonResponse({&quot;message&quot;: &quot;KEY_ERROR&quot;}, status=400)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[공공기관 해킹관련 기사를 보고]]></title>
            <link>https://velog.io/@full_accel/%EA%B3%B5%EA%B3%B5%EA%B8%B0%EA%B4%80-%ED%95%B4%ED%82%B9%EA%B4%80%EB%A0%A8-%EA%B8%B0%EC%82%AC%EB%A5%BC-%EB%B3%B4%EA%B3%A0</link>
            <guid>https://velog.io/@full_accel/%EA%B3%B5%EA%B3%B5%EA%B8%B0%EA%B4%80-%ED%95%B4%ED%82%B9%EA%B4%80%EB%A0%A8-%EA%B8%B0%EC%82%AC%EB%A5%BC-%EB%B3%B4%EA%B3%A0</guid>
            <pubDate>Sun, 13 Dec 2020 16:01:35 GMT</pubDate>
            <description><![CDATA[<p>&quot;해킹관련 지식이 없는 기자도 뚫을 만큼 공공기관 홈페이지의 보안이 허술하다!&quot; 라는 내용의 기사를 보았다.</p>
<p>관련 기사:
<a href="https://www.ytn.co.kr/_ln/0134_202010071353358166">https://www.ytn.co.kr/_ln/0134_202010071353358166</a>
영상 재생이 안되면 아래의 링크를 이용하세요.
<a href="https://search.naver.com/search.naver?where=nexearch&amp;sm=top_hty&amp;fbm=1&amp;ie=utf8&amp;query=%5B%EC%9E%90%EB%A7%89%EB%89%B4%EC%8A%A4%5D+&quot;%EA%B8%B0%EC%9E%90%EA%B0%80+%EC%A7%81%EC%A0%91+%ED%95%B4%ED%82%B9+%EC%84%B1%EA%B3%B5&quot;...%EB%B3%B4%EC%95%88+%ED%97%88%EC%88%A0+%EB%81%9D%ED%8C%90%EC%99%95+%ED%99%88%ED%8E%98%EC%9D%B4%EC%A7%80">https://search.naver.com/search.naver?where=nexearch&amp;sm=top_hty&amp;fbm=1&amp;ie=utf8&amp;query=[자막뉴스]+&quot;기자가+직접+해킹+성공&quot;...보안+허술+끝판왕+홈페이지</a></p>
<p>나는 과거에 보안장비 엔지니어로 일했었는데, 딱 이 문제 때문에 야근을 했던 기억이 새록새록 떠올랐다. 추억도 돋는 김에 관련 썰을 풀면서 기사의 팩트 체크도 해보고자 한다.</p>
<hr>
<h1 id="기사의-개요">기사의 개요</h1>
<ul>
<li>대한민국 공공기관 홈페이지에 로그인할 때 입력된 아이디와 패스워드를 기자가 손쉽게 해킹(?)했다.<ul>
<li>이 때 wireshark로 스니핑한 패스워드를 보여주는데 깨알같이 test1q2w3e 이다.(1q2w3e 내지 1q2w3e4r 은 대한민국 국군 1급 기밀이다.)</li>
</ul>
</li>
<li>해킹관련 지식이 없는 기자도 해킹할 정도로 보안이 허술다.</li>
<li>왜 그런고 하니 https를 적용하면 &quot;모바일로 접속할 경우 오류가 생긴다&quot;는 이유로 이를 중단했습니다고 한다. (???)</li>
<li>아무튼 얘네들은 잘못했다.</li>
</ul>
<h1 id="기사-해설">기사 해설</h1>
<ul>
<li>전체적으로는 맞는 얘기를 하긴하는데... 뭔가 좀 애매한 것 같다...</li>
</ul>
<h2 id="기자가-사용한-프로그램wireshark은-해킹프로그램이라고-말하기엔-무리가-있다">기자가 사용한 프로그램(wireshark)은 해킹프로그램이라고 말하기엔 무리가 있다.</h2>
<p>기자가 해킹(?) 시연에 사용한 프로그램은 wireshark 라는 툴이다. 이 프로그램을 굳이 정의 내리자면 네트워크 트래픽 분석 툴이라고 보는 게 맞을 것 같다. 그냥 밑도 끝도 없이 해킹 프로그램이 아니라...</p>
<p><img src="https://images.velog.io/images/full_accel/post/69a29d5c-b2d2-47c2-a7a2-182c079527fc/image.png" alt=""></p>
<p>기사 논리대로 가면 식칼은 살인 도구이고 모든 컴퓨터는 해킹 장비이다. 오바 좀 더하면 벽돌도 건축자재가 아니라 뚝배기 깨는 흉기이다.</p>
<h2 id="왜-저런-사단이-벌어지는가">왜 저런 사단이 벌어지는가?</h2>
<ul>
<li>GPKI 인증서가 웹브라우저 메이커에게 제대로 인정받지 못했기 때문이다.</li>
<li>참조: <a href="https://zdnet.co.kr/view/?no=20181227003039">https://zdnet.co.kr/view/?no=20181227003039</a></li>
</ul>
<p><img src="https://images.velog.io/images/full_accel/post/f6522913-5318-4686-8263-f4dfa390c731/image.png" alt=""></p>
<h2 id="나는-왜-야근을-했었나">나는 왜 야근을 했었나?</h2>
<ul>
<li>담당 고객사(공공)에서 저 GPKI 인증서 때문에 모바일 접속시 경고 메시지가 출력되는 걸 아주 못마땅하게 생각하던 훌륭한 마인드의 공무원님께서 작업을 지시하셨다.</li>
<li>공무원님 말씀: GPKI 말고 싸제 인증서 구매했으니 교체해 주세요.(역시 군대에서 배운대로 싸제가 좋은 것 같다.)</li>
<li>공무원님 말씀 해석<ul>
<li>인증서 교체하면 어쨋거나 한 번은 서비스 끊기니까 당연히 저녁에 작업(야근)해야하는거  아시죠?</li>
<li>서비스 끊기는 작업이니까 당연히 작업계획서 써오셔야 하는거 아시죠?</li>
</ul>
</li>
</ul>
<h2 id="저-해킹은-어떻게-시연했나">저 해킹(?)은 어떻게 시연했나?</h2>
<ul>
<li>아마도 추측컨데 대한민국 네트워크 말단을 장악하고 있는 i사의 장비에서 포트미러링 설정하여 모든 패킷을 스니핑하고</li>
<li>스니핑된 패킷을 wireshark로 열어봤을 것 같다.
<img src="https://images.velog.io/images/full_accel/post/283c7eef-9c0c-44eb-bbe4-297dc82f43b0/image.png" alt=""></li>
<li>i사 공유기로 클릭 몇 번하면 포트미러링이 가능하다. </li>
<li>제발 공유기 관리자 페이지 비밀번호를 어려운 것으로 바꾸자.<ul>
<li>그리고 그냥 잊어버리자. </li>
<li>어차피 처음 세팅하고 다시 들어올 일이 거의 없으니. </li>
<li>문제 생기면 그냥 리셋 버튼 누르고 다시 설정하면 그만이다.</li>
</ul>
</li>
</ul>
<h3 id="포트-미러링이란">포트 미러링이란?</h3>
<p>말 그대로 특정 port(여기서는OSI 4계층의 주소인 port가 아니라, 물리적인 통신장비에 UTP 케이블이 연결되는 그 물리적인 port)로 들어가고 나오는 모든 네트워크 트래픽에 대해서 미러링(거울로 보듯이, 트래픽을 카피)하겠다는 것이다.</p>
<p>즉, 내가 특정 포트에 포트 미러링을 설정하면 해당 포르트를 지나는 모든 트래픽을 나도 받아볼 수 있게된다.</p>
<h2 id="그래서-결론은">그래서 결론은?</h2>
<h3 id="gpki-인증서가-해외-브라우저-제조업체에게-인정받지-못해서-발생한-사단이다">GPKI 인증서가 해외 브라우저 제조업체에게 인정받지 못해서 발생한 사단이다.</h3>
<ul>
<li>웹서비스를 안전하게 제공하기 위해서는 SSL이라는 기술을 사용해야 한다.</li>
<li>이를 위해서는 웹서버는 SSL 인증서를 탑재해야 한다.</li>
<li>그런데 이 SSL 인증서가 믿을만한가 아닌가는 전적으로 고객이 사용하는 웹브라우저가 판단한다.</li>
<li>즉, 웹서버가 SSL 인증서를 가지고 있어도 웹브라우저가 부적절한 인증서라고 판단하면 &quot;!연결이 비공개로 설정되어 있지 않습니다.&quot; 라는 무서운 화면이 출력된다.</li>
<li>대한민국에는 GPKI(행정전자서명)이라는 대한민국 정부 주도의 인증서가 있다.</li>
<li>공공기관들이 당연히 이 인증서를 탑재했는데,</li>
<li>해외 유명 브라우저들(크롬 등)은 모바일 버전에 대해서 GPKI(행정전자서명) 인증서가 적절하지 않다고 판단했다.</li>
<li>그래서 GPKI(행정전자서명) 인증서를 탑재한 홈페이지에 접속하면 &quot;!연결이 비공개로 설정되어 있지 않습니다.&quot; 라는 무서운 화면을 보여줬다.</li>
</ul>
<h3 id="위-기사에-나온-공공기관이-잘못했나">위 기사에 나온 공공기관이 잘못했나?</h3>
<p>당연히 잘못했다고 본다. 문제를 인지한 즉시 적절한 외산 인증서로 교체하여 모바일 브라우저의 경고창을 사용자들이 보지 않도록 했어야 했다. </p>
<h3 id="그럼-다른-부처는-잘못이-없나">그럼 다른 부처는 잘못이 없나?</h3>
<p>당연히 근본적인 문제는 GPKI(행정전자서명)에 있다고 본다. 애초에 잘 만들어서 브라우저 제조업체가 GPKI(행정전자서명) 인증서를 안전한 인증서라고 판단했으면 이런 일 자체가 발생하지 않았을 것이다. 더불어 매년마다 인증서를 갱신하면서 외국의 인증서 제조업체에 비용도 지불하지 않아도 되었을 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OverTheWire: Bandit - Level 4 → Level 5]]></title>
            <link>https://velog.io/@full_accel/OverTheWire-Bandit-Level-4-Level-5-uldu4tmp</link>
            <guid>https://velog.io/@full_accel/OverTheWire-Bandit-Level-4-Level-5-uldu4tmp</guid>
            <pubDate>Sun, 13 Dec 2020 14:10:17 GMT</pubDate>
            <description><![CDATA[<h1 id="bandit-level-4-→-level-5---문제-원문">Bandit Level 4 → Level 5 - 문제 원문</h1>
<hr>
<p><a href="https://overthewire.org/wargames/bandit/bandit5.html">https://overthewire.org/wargames/bandit/bandit5.html</a></p>
<p>Level Goal
The password for the next level is stored in the only human-readable file in the inhere directory. Tip: if your terminal is messed up, try the “reset” command.</p>
<p>Commands you may need to solve this level
ls, cd, cat, file, du, find</p>
<h1 id="해석">해석</h1>
<hr>
<ul>
<li>패스워드는 inhere 경로의 <strong>인간이 읽을 수 있는(human-readable)</strong> 파일에 있다.</li>
</ul>
<h1 id="공략">공략</h1>
<hr>
<p>이번 레벨 역시 쉽다.</p>
<h2 id="상황-파악">상황 파악</h2>
<pre><code class="language-bash">bandit4@bandit:~$ ls
inhere
bandit4@bandit:~$ cd inhere/                    [1]
bandit4@bandit:~/inhere$ ls                    [2]
-file00  -file01  -file02  -file03  -file04  -file05  -file06  -file07  -file08  -file09
bandit4@bandit:~/inhere$ file ./-file01                [3]
./-file01: data
bandit4@bandit:~/inhere$ cat ./-file00                [4]
▒�/`2ғ▒%▒▒rL~5▒g▒▒ ▒▒▒▒▒bandit4@bandit:~/inhere$
</code></pre>
<ul>
<li>[1] inhere 경로로 이동한다.</li>
<li>[2] <code>ls</code>로 확인하니 뭐가 많다.</li>
<li>[3] <code>file ./-file01</code>로 확인하니 data 파일이다. </li>
<li>[4] <code>cat ./-file00</code>으로 찍어보니 data 파일은 인간이 읽을 수 없다. human-readable 이 이런 뜻이였다.</li>
<li>사이즈를 보아하니 저 여러개의 파일 중에 human-readable한 파일이 있긴 한가보다.</li>
<li>0번파일부터 9번 파일까지 다 찍어보는건 수능 수리영역 주관식 수열 문제를 풀 때  100번째 항 찾기를 손으로 푸는 것 같은 근성을 부리는 것 같아 찝찝하다. 출제자의 의도를 존중해줘야 할 것 같다.</li>
</ul>
<h2 id="해결-방법-asterisk-별표를-사용한다">해결 방법: *(asterisk, 별표)를 사용한다.</h2>
<pre><code class="language-bash">bandit4@bandit:~/inhere$ file ./*                [1]
./-file00: data
./-file01: data
./-file02: data
./-file03: data
./-file04: data
./-file05: data
./-file06: data
./-file07: ASCII text                        [2]
./-file08: data
./-file09: data

bandit4@bandit:~/inhere$ cat ./-file07                [3]
k??????????????????????????????</code></pre>
<ul>
<li>[1] <code>file ./*</code>를 입력하여 현재 경로의 모든 파일을 의미하는 <code>./*</code>를 file을 인자로 넘겨 준다.</li>
<li>[2] 07번 파일만 ASCII text 이다.</li>
<li>[3] <code>cat</code>으로 열어보니 패스워드 같은 것이 보인다.</li>
</ul>
<p>다음 단계로 넘어가자
<code>ssh -p 2220 bandit5@bandit.labs.overthewire.org</code></p>
<h3 id="조금-더-세련된-해결-방법-파이프라인에-grep을-사용">조금 더 세련된 해결 방법: |(파이프라인)에 grep을 사용</h3>
<pre><code class="language-bash">bandit4@bandit:~/inhere$ file ./* | grep &quot;text&quot;            [1]
./-file07: ASCII text                        [2]
bandit4@bandit:~/inhere$</code></pre>
<ul>
<li>human-readable 이라고 했으니 대충 text 파일이라고 넘겨 짚고 아래의 명령어를 사용해서 text 파일만 출력해 본다.</li>
<li>[1] <code>file ./* | grep &quot;text&quot;</code> <ul>
<li>현재 경로의 모든 파일에 대해서 <code>file</code> 명령어를 사용하면서 출력된 결과를 </li>
<li><code>|</code> (파이프라인) 을 사용하여 <code>grep</code> 명령어에 전달하고</li>
<li><code>grep</code>은 전달받은 내용에서 text라는 문자열을 검색하여 </li>
<li>[2] 해당되는 라인만 출력해준다.</li>
</ul>
</li>
</ul>
<h1 id="tmi">TMI</h1>
<hr>
<ul>
<li>리눅스에서 <code>./*</code>(asterisk, 별표)는 현재 경로의 모든 것을 의미한다.</li>
<li>리눅스에는 <code>sudo rm -rf /*</code> 라는 지옥에서 온 명령어가 있다.</li>
<li><code>|</code>(파이프라인)은 입출력의 방향을 바꾸어 준다.<ul>
<li><code>ls | grep &quot;mysql&quot;</code>의 경우 <code>ls</code> 명령어로 출력한 현재 디렉토리의 내용을 <code>grep</code> 명령어의 입력으로 전달해 준다. <code>grep</code> 명령어는 전달받은 내용에서 &quot;mysql&quot;이라는 텍스트가 포함된 라인만 출력해준다.</li>
</ul>
</li>
<li><code>grep</code>(global regular expression print): 위에서 사용한 예와 같이 입력으로 들어온 텍스트에서 원하는 텍스트가 포함된 라인만 출력할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[OverTheWire: Bandit - Level 3 → Level 4]]></title>
            <link>https://velog.io/@full_accel/OverTheWire-Bandit-Level-3-Level-4-axl8wsen</link>
            <guid>https://velog.io/@full_accel/OverTheWire-Bandit-Level-3-Level-4-axl8wsen</guid>
            <pubDate>Sun, 13 Dec 2020 13:39:54 GMT</pubDate>
            <description><![CDATA[<h1 id="bandit-level-3-→-level-4---문제-원문">Bandit Level 3 → Level 4 - 문제 원문</h1>
<hr>
<p><a href="https://overthewire.org/wargames/bandit/bandit4.html">https://overthewire.org/wargames/bandit/bandit4.html</a></p>
<p>Level Goal
The password for the next level is stored in a hidden file in the inhere directory.</p>
<p>Commands you may need to solve this level
ls, cd, cat, file, du, find</p>
<h1 id="해석">해석</h1>
<hr>
<ul>
<li>패스워드는 inhere 경로의 숨긴 파일에 있다.</li>
</ul>
<h1 id="공략">공략</h1>
<hr>
<p>이번 레벨도 쉽다.</p>
<pre><code class="language-bash">bandit3@bandit:~$                        [1]
bandit3@bandit:~$ ls                        [2]
inhere                                
bandit3@bandit:~$ cd inhere/
bandit3@bandit:~/inhere$ ls                    [3]
bandit3@bandit:~/inhere$ ls -al                    [4]
total 12
drwxr-xr-x 2 root    root    4096 May  7 20:14 .
drwxr-xr-x 3 root    root    4096 May  7 20:14 ..
-rw-r----- 1 bandit4 bandit3   33 May  7 20:14 .hidden
bandit3@bandit:~/inhere$ file .hidden                [5]
.hidden: ASCII text
bandit3@bandit:~/inhere$ cat .hidden                [6]
p??????????????????????????????</code></pre>
<ul>
<li>[1] 접속하니 홈 디렉토리(~)이다.</li>
<li>[2] ls로 확인하니 과연 inhere라는 경로가 있다.</li>
<li>[3] inhere로 이동하여 ls로 확인하니 아무것도 없다.</li>
<li>[4] ls -al로 경로내의 모든 파일을 확인하니 &quot;.&quot;, &quot;..&quot;, &quot;.hidden&quot; 이라는 녀석들이 보인다. </li>
<li>[5] file .hidden으로 찍어보니 ASCII text 파일이다.</li>
<li>[6] cat .hidden으로 열어보니 패스워드 같이 생긴 것이 보인다.</li>
</ul>
<p>다음 단계로 넘어가자
<code>ssh -p 2220 bandit4@bandit.labs.overthewire.org</code></p>
<h1 id="tmi">TMI</h1>
<hr>
<h2 id="리눅스의-숨김-파일경로">리눅스의 숨김 파일/경로</h2>
<ul>
<li>리눅스에서는 파일/경로를 숨기고자 할 때 파일명 앞에 <code>.</code>(점)을 찍는다.<pre><code class="language-bash">ls --help
...
-a, --all                  do not ignore entries starting with .
-A, --almost-all           do not list implied . and ..
...</code></pre>
</li>
<li>숨김 파일/경로를 확인하려면 <code>ls</code>에 옵션으로 <code>-a</code>를 주면 된다. -&gt; <code>ls -al</code></li>
<li><code>-A</code> 옵션을 주면 <code>.</code>(현재경로), <code>..</code>(상위경로)를 제외한 모든 파일/경로를 출력한다.</li>
</ul>
<h2 id="윈도우에서-git-파일">윈도우에서 .git 파일</h2>
<p><img src="https://images.velog.io/images/full_accel/post/cd15bc09-76b1-4b23-a754-1bfb1d74d76b/image.png" alt=""></p>
<ul>
<li>윈도우에서도 <code>.</code>(점)으로 시작하는 파일/경로는 숨긴다는 리눅스의 전통을 존중하는 건지 (아니면 8조나 주고 깃허브를 인수해서 그런건지) <code>git init</code> 명령어로 생성되는 <code>.git</code> 폴더는 자동으로 숨김처리 해준다.</li>
<li>Pycharm을 사용하면 자동으로 생성되는 <code>.idea</code> 폴더는 자동으로 숨김처리 안해준다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[OverTheWire: Bandit - Level 2 → Level 3]]></title>
            <link>https://velog.io/@full_accel/OverTheWire-Bandit-Level-2-Level-3-5hxp1vdu</link>
            <guid>https://velog.io/@full_accel/OverTheWire-Bandit-Level-2-Level-3-5hxp1vdu</guid>
            <pubDate>Sun, 13 Dec 2020 13:23:15 GMT</pubDate>
            <description><![CDATA[<h1 id="bandit-level-2-→-level-3---문제-원문">Bandit Level 2 → Level 3 - 문제 원문</h1>
<hr>
<p><a href="https://overthewire.org/wargames/bandit/bandit3.html">https://overthewire.org/wargames/bandit/bandit3.html</a></p>
<p>Level Goal
The password for the next level is stored in a file called spaces in this filename located in the home directory</p>
<p>Commands you may need to solve this level
ls, cd, cat, file, du, find</p>
<p>Helpful Reading Material
Google Search for “spaces in filename”</p>
<h1 id="해석">해석</h1>
<hr>
<ul>
<li>패스워드는 spaces in this filename에 있다.</li>
<li>space in this filename은 홈 디렉토리에 있다.</li>
</ul>
<h1 id="공략">공략</h1>
<hr>
<p>이번 단계도 어렵지 않다.</p>
<h2 id="상황-파악">상황 파악</h2>
<pre><code class="language-bash">bandit2@bandit:~$ ls                        [1]
spaces in this filename                        [2]
bandit2@bandit:~$ cat spaces in this filename            [3]
cat: spaces: No such file or directory
cat: in: No such file or directory            
cat: this: No such file or directory
cat: filename: No such file or directory</code></pre>
<ul>
<li>[1] 시작해보니 역시 홈 디렉토리(~)이다. 이동할 필요가 없다.</li>
<li>[2] ls로 찍어보니 정직하고 황당하게도 진짜 spaces in this filename 이라는 녀석이 있다.</li>
<li>[3] cat spaces in this filename 을 해보니 리눅스가 그게 뭔소리냐고 한다.</li>
</ul>
<h2 id="해결-방법-1---이스케이프-문자">해결 방법 1 - 이스케이프 문자</h2>
<ul>
<li>리눅스에게 공백을 &quot;문자&quot;로 인식시키기로 한다.</li>
<li>리눅스는 일반적인 경우에 공백을 문자로 인식하지 않는다.</li>
<li><code>cat ./file</code> 의 경우 <code>cat</code> 명령어의 인자로 <code>./file</code>을 받으라는 의미인데 이때 리눅스는 명령어와 인자를 구분하라는 의미로 공백을 해석했다.</li>
<li>백슬래쉬(보통 키보드 배열상 enter 키 위에 <code>₩</code> 의 모양을 가진 키)를 특수문자 앞에 써주면 리눅스는 특수문자를 그냥 &quot;문자&quot;로 해석한다.</li>
<li>이와 같은 역할을 하는 특수문자를 &quot;이스케이프 문자&quot;라고 한다.</li>
</ul>
<pre><code class="language-bash">bandit2@bandit:~$ cat spaces\ in\ this\ filename        [1]
U??????????????????????????????</code></pre>
<ul>
<li>[1] 이스케이프 문자로 공백을 표현하여 공백을 포함한 파일의 내용을 확인할 수 있다.(키를 찾았다.)</li>
</ul>
<h2 id="해결-방법-2---자동-완성">해결 방법 2 - 자동 완성</h2>
<ul>
<li>리눅스의 자동완성을 이용하기로 한다.</li>
<li>현재 디렉토리에서 <code>cat spa</code> 정도만 입력하고 <code>tab</code> 키를 입력하면 문장이 자동완성된다.</li>
<li>이때 공백에 대한 이스케이프 문자도 자동으로 입력된다.<ul>
<li>이스케이프 문자를 사용하면 리눅스에서 공백을 문자로 인식시킬 수 있다.<pre><code class="language-bash">bandit2@bandit:~$ cat spaces\ in\ this\ filename        [1]
U??????????????????????????????</code></pre>
</li>
</ul>
</li>
<li>[1] cat spa [tab 키 입력하면]<ul>
<li>cat spaces\ in\ this\ filename 까지 자동완성된다. 개꿀!</li>
</ul>
</li>
</ul>
<h2 id="해결-방법-3---따옴표">해결 방법 3 - 따옴표</h2>
<pre><code class="language-bash">bandit2@bandit:~$ cat &quot;spaces in this filename&quot;            [1]
U??????????????????????????????</code></pre>
<ul>
<li>[1] 공백을 포함한 문자열을 따옴표(&quot;)를 감싸서 리눅스에 문자열로 인식시킬 수 있다.</li>
</ul>
<p>다음 단계로 넘어가자
<code>ssh -p 2220 bandit3@bandit.labs.overthewire.org</code></p>
<h1 id="tmi">TMI</h1>
<hr>
<h2 id="이스케이프-부호">이스케이프 부호</h2>
<p>영문 출판물에서 가장 많이 사용되는 2기 점차체계에서 가능한 적은 기호로 영문 대소문자를 모두 표현하기 위해 이스케이프라 부호라는 개념을 사용한다. 즉 a에 해당하는 점자를 그냥 쓰면 소문자이지만 이스케이프 문자를 의미하는 점자가 앞에 오고 그 뒤에 소문자 a를 의미하는 점자가 오면 이를 대문자 A라고 규칙을 정한 것이다.</p>
<h2 id="시프트-부호">시프트 부호</h2>
<p>2기 점자체계에서는 숫자를 표현하기 위해 a를 1에 대응시키고 b를 2에 대응시키고... j를 0에 대응시킨다. 점자 중에서 자신 뒤로 오는 점자는 영문이 아니라 숫자라고 인식시키는 부호가 있고, 숫자로 인식하는 구간이 끝났음을 알리는 점자가 있다. 이러한 부호들을 일반적으로 선행 부호 또는 시프트 부호라고 한다.</p>
<h1 id="tmi-참조">TMI 참조</h1>
<hr>
<p>CODE by 찰스 팻졸드, Chapter3 점자와 이진부호</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OverTheWire: Bandit - Level 1 → Level 2]]></title>
            <link>https://velog.io/@full_accel/OverTheWire-Bandit-Level-1-Level</link>
            <guid>https://velog.io/@full_accel/OverTheWire-Bandit-Level-1-Level</guid>
            <pubDate>Sun, 06 Dec 2020 14:55:44 GMT</pubDate>
            <description><![CDATA[<h1 id="bandit-level-1-→-level-2---문제-원문">Bandit Level 1 → Level 2 - 문제 원문</h1>
<hr>
<p><a href="https://overthewire.org/wargames/bandit/bandit1.html">https://overthewire.org/wargames/bandit/bandit1.html</a>
Level Goal
The password for the next level is stored in a file called - located in the home directory</p>
<p>Commands you may need to solve this level
ls, cd, cat, file, du, find</p>
<p>Helpful Reading Material
Google Search for “dashed filename”
Advanced Bash-scripting Guide - Chapter 3 - Special Characters</p>
<h1 id="해석">해석</h1>
<hr>
<ul>
<li>패스워드는 <code>-</code>라는 파일에 저장되어 있다.</li>
<li><code>-</code> 파일은 홈 디렉토리에 있다.</li>
</ul>
<h1 id="공략">공략</h1>
<hr>
<p>이번 단계도 어렵지 않다.</p>
<pre><code class="language-bash">bandit1@bandit:~$ ls
-
bandit1@bandit:~$ file -
^C

bandit1@bandit:~$ cat -
^C

bandit1@bandit:~$ file ./-
./-: ASCII text
bandit1@bandit:~$ cat ./-
C??????????????????????????????
bandit1@bandit:~$</code></pre>
<ul>
<li>일단 시작부터 홈 디렉토리 <code>~</code> 이다. 다른 곳으로 이동할 필요가 없다.</li>
<li>현재 경로를 확인해 보니 <code>-</code> 라는 파일이 있다.</li>
<li><code>file -</code>로 찍어 보니 아무것도 나오지 않는다.</li>
<li><code>cat -</code>으로 열어봐도 아무것도 나오지 않는다.</li>
<li>아무래도 <code>-</code> 이라는 문자가 리눅스에서 예약된 특수문자라 <code>file</code>, <code>cat</code>에서 인자로 넘겨받지 못하는 것으로 보인다.</li>
<li>현재 경로에 있는 파일을 의미하는 <code>./</code> 를 사용하기로 한다.<ul>
<li><code>file ./-</code> 로 찍어보니 ASCII text 파일이다.</li>
<li><code>cat ./-</code> 로 열어보니 key file처럼 생긴 텍스트가 보인다.</li>
</ul>
</li>
</ul>
<p>다음 단계로 넘어가자
<code>ssh -p 2220 bandit2@bandit.labs.overthewire.org</code></p>
<h1 id="tmi">TMI</h1>
<hr>
<h2 id="--의-의미"><code>-</code> 의 의미</h2>
<ul>
<li><code>-</code> 는 리눅스 명령어에서 옵션을 지정할 때 자주 사용된다.</li>
<li>ex) <code>ls</code> 명령어에 옵션으로 <code>-A</code>를 주어서 현재 경로의 <code>.</code>, <code>..</code>을 제외한 모든 파일을 출력할 수 있다.
```bash
bandit1@bandit:~$ ls</li>
<li>bandit1@bandit:~$ ls -A</li>
<li>.bash_logout  .bashrc  .profile
bandit1@bandit:~$
```</li>
<li><code>cat -</code> 이라고 입력하면 리눅스는 사용자가 옵션을 넣다가 만 것으로 인식한다.<ul>
<li>즉 <code>-</code>를 명령어 자신이 넘겨받는 인자가 아니라 옵션 앞에 오는 문자로 인식한다.</li>
<li><code>cat ./-</code> 이라고 입력하면 현재경로<code>./</code>에 있는 파일 <code>-</code>을 인자로 받을 수 있다.</li>
</ul>
</li>
</ul>
<h2 id="-의-의미">./ 의 의미</h2>
<ul>
<li><code>./</code>는 리눅스에서 현재 경로를 의미한다.</li>
<li>현재 경로에 readme 라는 파일이 있다면, <code>cat readme</code> 나 <code>cat ./readme</code> 나 일단 동일하게 동작하나 <code>cat ./readme</code>는 명시적으로 현재 디렉토리의 readme 파일에 대해 <code>cat</code>을 실행하라는 의미이다.</li>
</ul>
<h2 id="명령어-옵션-확인하는-방법">명령어 옵션 확인하는 방법</h2>
<ul>
<li>명령어 <code>--help</code> 로 명령어의 옵션을 간단히 확인할 수 있다.<pre><code class="language-bash">bandit1@bandit:~$ cat --help
Usage: cat [OPTION]... [FILE]...
Concatenate FILE(s) to standard output.
</code></pre>
</li>
</ul>
<p>With no FILE, or when FILE is -, read standard input.</p>
<p>  -A, --show-all           equivalent to -vET
  -b, --number-nonblank    number nonempty output lines, overrides -n
  -e                       equivalent to -vE
  ...</p>
<pre><code>- `man`으로 명령어의 옵션을 아주 자세히 확인할 수 있다.

```bash
bandit1@bandit:~$ man cat</code></pre><p><img src="https://images.velog.io/images/full_accel/post/8989b06a-6050-41cb-a042-db42388213d4/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OverTheWire: Bandit - Level 0]]></title>
            <link>https://velog.io/@full_accel/OverTheWire-Bandit-Level-0</link>
            <guid>https://velog.io/@full_accel/OverTheWire-Bandit-Level-0</guid>
            <pubDate>Sun, 06 Dec 2020 14:54:51 GMT</pubDate>
            <description><![CDATA[<h1 id="bandit-wargame을-진행하는-방법">bandit wargame을 진행하는 방법</h1>
<hr>
<ul>
<li>bandit은 wargame으로 각 단계마다 의도적으로 설계된 시스템의 취약점을 찾으면서 시스템에 대해 학습하는 것이 목표이다.</li>
<li>bandit의 각 단계에서 취약점을 찾으면 이를 이용하여 키를 찾을 수 있다.</li>
<li>키는 다음 단계의 패스워드이다.</li>
<li>동일한 bandit 서버(bandit.labs.overthewire.org)에 badnit1 아이디로 접속하면 level 1이고, bandit2 아이디로 접속하면 level2이다.</li>
<li>levle1에서 키를 찾았다면 곧 bandit2 아이디의 패스워드이다.</li>
<li>각 아이디로 접속하면 그에 맞는 level의 문제가 세팅되어 있다.</li>
<li>최종 목표는 level34까지 가는 것이다.</li>
</ul>
<h1 id="bandit-level-0---문제-원문">Bandit Level 0 - 문제 원문</h1>
<hr>
<p><a href="https://overthewire.org/wargames/bandit/bandit0.html">https://overthewire.org/wargames/bandit/bandit0.html</a></p>
<p>Level Goal
The goal of this level is for you to log into the game using SSH. The host to which you need to connect is bandit.labs.overthewire.org, on port 2220. The username is bandit0 and the password is bandit0. Once logged in, go to the Level 1 page to find out how to beat Level 1.</p>
<p>Commands you may need to solve this level
ssh</p>
<p>Helpful Reading Material
Secure Shell (SSH) on Wikipedia
How to use SSH on wikiHow</p>
<h1 id="문제-해석">문제 해석</h1>
<hr>
<ul>
<li><p>이번 단계의 목표는 게임에 SSH를 사용하여 로그인하는 것이다.</p>
</li>
<li><p><strong><a href="http://bandit.labs.overthewire.org">bandit.labs.overthewire.org</a></strong>로 로그인하는데 포트번호는 2220번이고, 아이디 패스워드는 bandit0이다.</p>
</li>
<li><p>ssh 명령어가 유용할 것이다.</p>
</li>
</ul>
<h1 id="공략">공략</h1>
<hr>
<p>이 단계는 공략이고 뭐고 없다. 그냥 알려준 주소로 알여준 아이디와 패스워드로 로그인하면 끝이다. </p>
<p>다만 어떻게 접속하는지(SSH로 원격지 서버에 어떻게 접속하는지)를 알아내야 한다.(구글링하면 바로 나온다.) </p>
<p>추가적으로 SSH로 원격지 서버접속에 어떤 프로그램을 사용할지도 정해야 한다. 접속용 프로그램들은 아주 많다.</p>
<ul>
<li>리눅스 쉘</li>
<li>윈도우 명령프롬프트(CMD)</li>
<li>putty</li>
<li>cygwin</li>
<li>CMDer</li>
<li>그 밖에 SecureCRT, SuperPutty, Xshell(무려 국산) 등의 프로그램을 활용할 수 있다.</li>
</ul>
<p>취향것 자신에게 맞는 프로그램을 사용하여 접속하면 된다.</p>
<p>각 프로그램의 간략한 소개</p>
<ul>
<li>윈도우 명령프롬프트<ul>
<li>우리가 익히 아는 검은 화면에 하얀 글씨 나오는 그것</li>
<li><code>윈도우키 + R</code> 로 실행창을 띄우고 <code>cmd</code>를 입력하면 바로 실행된다.</li>
<li>윈도우의 명령어를 실행할 수 있다.</li>
</ul>
</li>
<li>putty<ul>
<li>윈도우를 위한 무료 SSH 및 telnet 클라이언트</li>
<li>좋게 말하면 필요한 기능만 있고 그냥 말하면 저세상 인터페이스</li>
<li>익숙해 지면 나름 편함</li>
</ul>
</li>
<li>cygwin<ul>
<li>윈도우에서 리눅스 쉘을 쓸 수 있도록 해주는 프로그램</li>
<li><code>ls</code>, <code>du</code>, <code>mkdir</code> 등의 리눅스 명령어로 윈도우를 제어할 수 있다.</li>
</ul>
</li>
<li>CMDer<ul>
<li>윈도우에서 리눅스 쉘을 쓸 수 있도록 해주는 프로그램</li>
<li><code>ls</code>, <code>du</code>, <code>mkdir</code> 등의 리눅스 명령어로 윈도우를 제어할 수 있다.</li>
<li>cygwin 보다 예쁘다.</li>
<li>cygwin 보다 느리다.</li>
</ul>
</li>
</ul>
<p>여기서는 <a href="https://velog.io/@full_accel/Windows-WSL2%EB%A1%9C-%EC%9A%B0%EB%B6%84%ED%88%AC-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0">WSL2로 설치한 리눅스</a>의 쉘을 이용하기로 한다.</p>
<p>리눅스에 ssh가 설치되지 않은 경우 아래의 명령어로 update 한 번 해주고 ssh를 설치한다.</p>
<pre><code>sudo apt-get update
sudo apt-get install ssh </code></pre><p>이제 bandit level0에 접속하자!</p>
<pre><code> ssh -p 2220 bandit0@bandit.labs.overthewire.org
 This is a OverTheWire game server. More information on http://www.overthewire.org/wargames

bandit0@bandit.labs.overthewire.org&#39;s password:</code></pre><p>패스워드를 물어본다. <strong>bandit0</strong>를 입력하면 된다.(원래 텍스트를 입력해도 눈에 보이지 않는다. 그냥 bandit0 입력하고 enter 키를 누르면 된다.)</p>
<pre><code>bandit0@bandit.labs.overthewire.org&#39;s password:
Linux bandit.otw.local 5.4.8 x86_64 GNU/Linux

      ,----..            ,----,          .---.
     /   /   \         ,/   .`|         /. ./|
    /   .     :      ,`   .&#39;  :     .--&#39;.  &#39; ;
   .   /   ;.  \   ;    ;     /    /__./ \ : |
  .   ;   /  ` ; .&#39;___,/    ,&#39; .--&#39;.  &#39;   \&#39; .
  ;   |  ; \ ; | |    :     | /___/ \ |    &#39; &#39;
  |   :  | ; | &#39; ;    |.&#39;;  ; ;   \  \;      :
  .   |  &#39; &#39; &#39; : `----&#39;  |  |  \   ;  `      |
  &#39;   ;  \; /  |     &#39;   :  ;   .   \    .\  ;
   \   \  &#39;,  /      |   |  &#39;    \   \   &#39; \ |
    ;   :    /       &#39;   :  |     :   &#39;  |--&quot;
     \   \ .&#39;        ;   |.&#39;       \   \ ;
  www. `---` ver     &#39;---&#39; he       &#39;---&quot; ire.org


Welcome to OverTheWire!
(...생략...)

  Enjoy your stay!

bandit0@bandit:~$</code></pre><p>위와 같이 프롬프트가 떨어지면 bandit0 클리어다!</p>
<h1 id="tmi">TMI</h1>
<hr>
<h2 id="telnet과-ssh">telnet과 SSH</h2>
<p>SSH에 대해서 아주아주 간단히 말하자면 &quot;비교적 매우 안전한 통신 방법&quot;이다. 옛날 옛적에는 클라이언트가 서버와 연결할 때 Telnet이라는 기술(원체 취약해서 요즘엔 윈도우에서 기본적으로 못쓰게 막혀있다. 그런데 어거지로 사용하려면 사용할 수는 있다.)을 사용하였는데, 이게 보안을 고려하고 만들어진 물건이 아니라 서버와 클라이언트 간의 통신을 평문(암호화되지 않은 문서)으로 주고 받았다.</p>
<p>해커가 중간에 트래픽을 확보(스니핑)하기만 하면 어떤 통신 내용을 주고 받는지 알 수 있었다. 반면 SSH는 통신 내용을 암호화 한다.(이름부터가 Secure SHell, SSH이다.) 따라서 해커가 중간에 통신 트래픽을 탈취하더라도 암호화된 문서만 볼 수 있어 비교적 매우 안전하다.</p>
<p>Telnet의 well known port는 23번이고, SSH는 22번이다.</p>
]]></description>
        </item>
    </channel>
</rss>